generator-confit
Version:
Yeoman generator for creating the development process, tools and a sample project for current-generation web applications
623 lines (519 loc) • 24.1 kB
YAML
# App configuration
app:
subGenerators: # This is the order that the sub-generators should be executed in. Try not to couple these together
- confit:buildBrowser
- confit:paths
- confit:buildAssets
- confit:buildCSS
- confit:buildJS
- confit:buildHTML
- confit:entryPoint
- confit:serverDev
- confit:serverProd
- confit:testUnit
- confit:testSystem
- confit:testVisualRegression
- confit:verify
- confit:documentation
- confit:release
- confit:sampleApp
- confit:zzfinish
packages:
- <<: *pkg_npm-run-all
- <<:
- <<: *pkg_cross-env
tasks:
- name: start
tasks: ['npm run dev']
description: Alias for `npm run dev` task
features:
- name: dev
tasks: ['cross-env NODE_ENV=development npm-run-all clean:dev --parallel verify:watch build:dev serve:dev']
description: Run project in development mode (verify code, create dev build into <%= paths.output.devDir %> folder, serve on **<%= serverDev.protocol + '://' + serverDev.hostname + ':' + serverDev.port %>**, watch for changes and reload the browser automatically)
features:
- name: build
tasks: ['cross-env NODE_ENV=production npm-run-all clean:prod build:prod']
description: Generate production build into <%= link(paths.output.prodDir) %> folder
features:
- name: build:serve
tasks: ['build', 'serve:prod']
description: Generate production build and serve on **<%= serverProd.protocol + '://' + serverProd.hostname + ':' + serverProd.port %>**'
features:
- name: clean:dev
tasks: ['rimraf <%= paths.output.devDir %>']
description:
features:
- name: clean:prod
tasks: ['rimraf <%= paths.output.prodDir %>']
description:
features:
# Frameworks are used by multiple generators
frameworks:
'': # This is not really a framework. It represents the configuration needed when there IS NO framework.
ES6:
entryPointFileName: ./<%- resources.sampleApp.demoDir %>app.js
TypeScript:
entryPointFileName: ./<%- resources.sampleApp.demoDir %>app.ts
frameworkPackages: {}
frameworkTestPackages: {}
AngularJS 1.x:
ES6:
entryPointFileName: ./<%- resources.sampleApp.demoDir %>app.js
TypeScript:
entryPointFileName: ./<%- resources.sampleApp.demoDir %>app.ts
frameworkPackages:
packages:
- <<:
- <<: *pkg_@types/angular
- <<: *pkg_@types/angular-mocks
frameworkTestPackages:
testPackages: # Test packages will be used *instead of* the framework packages, in the test harness!
- <<:
- <<: *pkg_angular-mocks
AngularJS 2.x:
TypeScript:
entryPointFileName: ./<%- resources.sampleApp.demoDir %>main.browser.ts
frameworkPackages:
packages: # All these files end up in the vendors bundle, created by the entryPoint buildTool
- <<: *pkg_@angular/platform-browser
- <<: *pkg_@angular/platform-browser-dynamic
- <<: *pkg_@angular/compiler
- <<: *pkg_@angular/core
- <<: *pkg_@angular/common
- <<: *pkg_rxjs/add/operator/map
- <<: *pkg_rxjs/add/operator/mergeMap
- <<: *pkg_core-js/es6/symbol # Don't include es6/promise as it breaks zone.js
- <<: *pkg_core-js/es6/object
- <<: *pkg_core-js/es6/function
- <<: *pkg_core-js/es6/parse-int
- <<: *pkg_core-js/es6/parse-float
- <<: *pkg_core-js/es6/number
- <<: *pkg_core-js/es6/math
- <<: *pkg_core-js/es6/string
- <<: *pkg_core-js/es6/date
- <<: *pkg_core-js/es6/array
- <<: *pkg_core-js/es6/regexp
- <<: *pkg_core-js/es6/map
- <<: *pkg_core-js/es6/set
- <<: *pkg_core-js/es6/weak-map
- <<: *pkg_core-js/es6/weak-set
- <<: *pkg_core-js/es6/typed
- <<: *pkg_core-js/es6/reflect
- <<: *pkg_core-js/es7/reflect
- <<: *pkg_zone.js/dist/zone
- <<: *pkg_ts-helpers
frameworkTestPackages:
testPackages: # Maps to Karma test.specs.js https://github.com/AngularClass/angular2-webpack-starter/blob/master/config/spec-bundle.js
- <<: *pkg_core-js/es6
- <<: *pkg_core-js/es7/reflect
- <<: *pkg_ts-helpers
- <<: *pkg_zone.js/dist/zone
- <<: *pkg_zone.js/dist/long-stack-trace-zone
- <<: *pkg_zone.js/dist/proxy
- <<: *pkg_zone.js/dist/sync-test
- <<: *pkg_zone.js/dist/jasmine-patch
- <<: *pkg_zone.js/dist/async-test
- <<: *pkg_zone.js/dist/fake-async-test
- <<: *pkg_rxjs/Rx
# Angular2 source code is loaded by each component that is being tested. So no need to include Angular2 here.
React (latest):
ES6:
entryPointFileName: ./<%- resources.sampleApp.demoDir %>app.jsx
frameworkPackages:
packages:
- <<:
- <<: *pkg_react-dom
frameworkTestPackages:
testPackages:
- <<:
- <<: *pkg_react-addons-test-utils
- <<:
buildAssets: {}
buildBrowser:
defaults:
browserSupport: ['latest']
supportedBrowsers:
latest:
label: Latest Versions (major browsers)
browserList: ['last 1 version']
latest2:
label: Latest 2 Versions (major browsers)
browserList: ['last 2 versions']
legacyIE:
label: Legacy Internet Explorer (9, 10, 11)
browserList: ['ie 9', 'ie 10', 'ie 11']
legacyMobile:
label: Legacy Mobile (Blackberry, Android Webview)
browserList: ['bb', 'Android Webview']
# CSS configuration
buildCSS:
defaults:
sourceFormat: stylus
sourceFormat:
css:
ext: ['css']
sass:
ext: ['sass', 'scss']
stylus:
ext: ['styl']
buildHTML: {}
buildJS:
defaults:
sourceFormat: ES6
outputFormat: ES6
# No default framework
showVendorScripts: true # Flag to indicate that whether the vendorScripts question in buildJS should be shown or not. Not used for Node projects.
sourceFormat:
ES6:
ext: ['js', 'jsx']
TypeScript:
ext: ['ts']
outputFormat:
- ES5
- ES6
readme:
extensionPoint:
buildJS.frameworkScripts: >
The `buildJS.frameworkScripts` array in <%= link(configFile) %> contains framework-specific scripts, and should not be modified.
If a sample project is generated, the additional framework scripts needed by the sample app will also appear here.
This property will be overwritten **every time** Confit is run.
buildJS.vendorScripts: >
The `buildJS.vendorScripts` array in <%= link(configFile) %> is designed to be edited manually.
This property should contain NPM module names and/or references to JavaScript files (files must start with `./`).
For example: `vendorScripts: ['jquery', './module/path/to/jsFile.js', 'moment/timezone', ...]`
configModules:
- condition: <%- buildJS.sourceFormat === 'ES6' %>
templateFiles: # We need to use Babel EVEN when outputFormat is NOT ES5 so that browser unit testing works (as the new unit testing plugin is tied to Babel)
- src: .babelrc.tpl
dest: .babelrc
overwrite: true
packages:
- <<: *pkg_babel-core
#- <<: *pkg_babel-runtime # TODO: This is the runtime for ES6 code - do we need this if we are not using the runtime-transform?
- <<: *pkg_babel-preset-es2015
#- <<: *pkg_babel-plugin-add-module-exports # Generate the "default" export when using Babel 6: http://stackoverflow.com/questions/34736771/webpack-umd-library-return-object-default
# This causes issues for Angular 1 sampleApp.
tasks: []
- condition: <%- buildJS.sourceFormat === 'TypeScript' %>
packages:
- <<:
- <<: *pkg_@types/node
templateFiles:
- src: tsconfig.json.tpl
dest: tsconfig.json
overwrite: true
- condition: <%- buildJS.framework.indexOf('AngularJS 1.x') > -1 %>
<<:
- condition: <%- buildJS.framework.indexOf('AngularJS 2.x') > -1 %>
<<:
- condition: <%- buildJS.framework.indexOf('React (latest)') > -1 %>
<<:
- condition: <%- buildJS.framework.indexOf('React (latest)') > -1 %>
packages:
- <<: *pkg_babel-preset-react-app
- <<: *pkg_eslint-config-react-app
- <<: *pkg_eslint-plugin-import
- <<: *pkg_eslint-plugin-jsx-a11y
- <<: *pkg_eslint-plugin-react
entryPoint:
readme:
extensionPoint:
entryPoint: >
The `entryPoint.entryPoints` object in <%= link(configFile) %> is designed to be edited manually.
It represents the starting-point(s) of the application (like a `main()` function). Normally an application has
one entry point, but it is possible to have more than one.
`entryPoint.entryPoints` must have at-least one property (e.g. `property: [file]`), where `file` is a list
of NPM module names and/or references to JavaScript files (file references must start with `./`);
# Path Defaults
paths:
prompts:
- name: input.srcDir
heading: |
Source-code paths
message: Path to SOURCE directory (relative to the current directory)
- name: input.modulesSubDir
message: Path to MODULES directory (relative to the SOURCE directory)
- name: input.assetsDir
message: Name of module ASSETS directory (for images, fonts)
- name: input.stylesDir
message: Name of module STYLES directory (for CSS)
- name: input.templateDir
message: Name of module TEMPLATE directory (for component HTML templates)
- name: input.unitTestDir
message: Name of module UNIT TEST directory
- name: input.systemTestDir
message: Name of module SYSTEM TEST (browser test) directory
- name: output.devDir
heading: |
Output paths
message: Path to DEV OUTPUT directory (relative to the current directory)
- name: output.prodDir
message: Path to PRODUCTION OUTPUT directory (relative to the current directory)
- name: output.assetsSubDir
message: Path to ASSETS sub-directory (relative to the OUTPUT directory)
- name: output.cssSubDir
message: Path to CSS sub-directory (relative to the OUTPUT directory)
- name: output.jsSubDir
message: Path to JS sub-directory (relative to OUTPUT directory)
- name: output.vendorJSSubDir
message: Path to VENDOR JS libraries sub-directory (relative to OUTPUT directory)
- name: output.reportDir
message: Path to TEST REPORTS directory (relative to the current directory)
- name: config.configDir
heading: |
Config paths
message: Path to CONFIG directory (relative to the current directory)
defaults:
input:
srcDir: src/
modulesSubDir: modules/
assetsDir: assets/
stylesDir: styles/
templateDir: template/
unitTestDir: unitTest/
systemTestDir: systemTest/
testDir: test/
output:
devDir: dev/
prodDir: dist/
assetsSubDir: assets/
cssSubDir: css/
jsSubDir: js/
vendorJSSubDir: vendor/
reportDir: reports/
config:
configDir: config/
pathsToGenerate:
- name: input.modulesDir
value: <%- paths.input.srcDir + '/' + paths.input.modulesSubDir %>
# README section for the template tags that will appear inside the README.md template
readme:
RM_DIR_STRUCTURE: |
## Directory Structure
Code is organised into modules which contain one-or-more components. This a great way to ensure maintainable code by encapsulation of behavior logic. A component is basically a self contained app usually in a single file or a folder with each concern as a file: style, template, specs, e2e, and component class. Here's how it looks:
```<% var maxDirLen = 30; %>
<%- pkg.name %>/
├──<%- rpad(paths.config.configDir, maxDirLen)%>* configuration files live here (e.g. webpack, <%- resources.documentation.configSubDir %>, <%- resources.testSystem.configSubDir %>, <%- resources.testUnit.configSubDir %>, <%- resources.testVisualRegression.configSubDir %>, <%- resources.verify.configSubDir %>)
│
├──<%- rpad(paths.input.srcDir, maxDirLen) %>* source code files should be here
│ └──<%- rpad(paths.input.modulesSubDir, maxDirLen - 4) %>* all source code modules|components|features should appear as sub-directories under this directory
│ ├──<%- rpad('common/', maxDirLen - 8) %>
│ ├──<%- rpad('featureA/', maxDirLen - 8) %>
│ └──<%- rpad('featureB/', maxDirLen - 8) %>
│ ├──<%- rpad(paths.input.assetsDir, maxDirLen - 12) %>
│ │ ├──<%- rpad('font', maxDirLen - 16) %>* fonts for this module
│ │ └──<%- rpad('img', maxDirLen - 16) %>* images for this module
│ ├──<%- rpad(paths.input.stylesDir, maxDirLen - 12) %>* css source code for this module
│ ├──<%- rpad(paths.input.templateDir, maxDirLen - 12) %>* HTML templates for this module
│ ├──<%- rpad(paths.input.systemTestDir, maxDirLen - 12) %>* system test specs for this module
│ ├──<%- rpad(paths.input.unitTestDir, maxDirLen - 12) %>* unit test specs for this module
│ └──<%- rpad(testVisualRegression.moduleTestDir, maxDirLen - 12) %>* visual regression test specs for this module (if enabled)
│
├──<%- rpad(paths.output.devDir, maxDirLen) %>* development-build code is output here (Webpack may keep it in memory for speed)
├──<%- rpad(paths.output.prodDir, maxDirLen) %>* production-build code is output here
│ ├──<%- rpad(paths.output.assetsSubDir, maxDirLen - 4) %>* all assets appear here, under module sub-folders. e.g.:
│ │ └──<%- rpad('featureB/', maxDirLen - 8) %>
│ │ ├──<%- rpad('font', maxDirLen - 12) %>
│ │ └──<%- rpad('img', maxDirLen - 12) %>
│ ├──<%- rpad(paths.output.cssSubDir, maxDirLen - 4) %>* compiled CSS files
│ ├──<%- rpad(paths.output.jsSubDir, maxDirLen - 4) %>* minified JS files
│ └──<%- rpad(paths.output.vendorJSSubDir, maxDirLen - 4) %>* minified vendor JS files
│
├──<%- rpad(paths.output.reportDir, maxDirLen) %>* test reports appear here<% if (documentation.generateDocs) { %>
│
├──<%- rpad(documentation.srcDir, maxDirLen) %>* source/content for the documentation website goes here
├──<%- rpad(documentation.outputDir, maxDirLen) %>* the documentation website is generated here<% } %>
│
├──<%- rpad(testVisualRegression.referenceImageDir, maxDirLen) %>* visual regression testing reference images (if enabled)
│
├──<%- rpad(configFile, maxDirLen) %>* the project config file generated by 'yo confit'
├──<%- rpad('CONTRIBUTING.md', maxDirLen) %>* how to contribute to the project
├──<%- rpad('README.md', maxDirLen) %>* this file
└──<%- rpad('package.json', maxDirLen) %>* NPM package description file
```
RM_NEXT_STEPS: |
## *Next Steps to Setup your Project*
Remove this section once you are comfortable updating your project.
- [ ] Update [package.json](package.json) with a nice description, then run `yo confit --skip-install --skip-run` and see the README.md file is updated
- [ ] Add a new **dependency** to your project:
- For a **source-code** dependency:
1. `npm i {nodeModule} --save`
1. Edit <%- link(configFile) %> and include {nodeModule} as an item inside the `buildJS.vendorScripts` array
1. `yo confit` to regenerate your build configuration
- For a **development** dependency:
1. `npm i {nodeModule} --save-dev`
1. Edit the configuration file(s) that will need to use this dependency in the areas of the file that will not be overwritten when `yo confit` is run.
For example:
```js
// Changes in this region will be preserved.
// START_CONFIT_GENERATED_CONTENT
// Changes in this region will be overwritten if `yo confit` is run again.
// END_CONFIT_GENERATED_CONTENT
// Changes in this region will be preserved.
```
- For a **test** dependency:
1. `npm i {nodeModule} --save`
1. Edit <%- link(configFile) %> and include {nodeModule} as an item inside the `testUnit.testDependencies` array
1. Run `yo confit` to regenerate your build configuration
<% if (release.useSemantic) { %>- [ ] Complete the installation of the **semantic release** tool:
1. Make sure you have:
- a GitHub login
- an NPM login
- a TravisCI login (though you can still proceed if you use a different CI tool)
1. Run `semantic-release-cli setup` to complete the installation
<% } -%>
<% if (release.checkCodeCoverage && app.repositoryType === 'GitHub') { %>- [ ] Install code coverage:
1. Make sure you have:
- a TravisCI login (though you can still proceed if you use a different CI tool)
- a [Coveralls](https://coveralls.io) account
1. Push your code to GitHub.
1. Login to [Coveralls](https://coveralls.io/).
1. Press Add Repo. You may need to Sync your GitHub repos to see your new repo in the list.
1. Select the repo and you will see a "Set Up Coveralls" page. Note the `repo_token` value.
1. Login to [Travis CI](https://travis-ci.org/).
1. Edit the settings for this repo (More Settings > Settings).
1. In the Environment Variables section, create a new envrionment variable called `COVERALLS_REPO_TOKEN` and set its value to the *repo_token* value shown on the "Set Up Coveralls" page, and press "Add".
1. Push another commit to GitHub and you should get a coverage report now!
<% } -%>
- [ ] Add a new module to `<%- paths.input.modulesDir %>`
- [ ] Run `npm start`, change the stylesheet and see the changes appear immediately
- [ ] Run `npm test` to execute the unit tests and see the test coverage
- [ ] Run `npm start && test:system` to execute the browser tests
<% if (release.commitMessageFormat === 'Conventional') { %>- [ ] Run `git cz` to commit changes with a conventional commit message
<% } -%>
# Sample App
sampleApp:
# There is a problem in eslintignore.yml.tpl whereby we want to refer to sampleApp.deomDir, but this variable also contains an EJS template
# To work around this issue, we change eslintignore.yml.tpl to have a 'browser' and 'node' version of the directory to ignore.
# This is not ideal, but less evil than changing all the generators to support this use-case.
demoDirName: demoModule/
demoDir: <%= paths.input.modulesSubDir %>demoModule/
# Master config
templateFiles:
- src: assets/**/*
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.assetsDir %>
overwrite: true
noParse: true
- src: systemTest/*
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.systemTestDir %>
overwrite: true
noParse: true
configModules:
- condition: <%= buildCSS.sourceFormat === 'css' %>
templateFiles:
- src: css/app.css
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.stylesDir %>app.css
overwrite: true
- src: css/iconFont.css
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.stylesDir %>iconFont.css
overwrite: true
- condition: <%= buildCSS.sourceFormat === 'sass' %>
templateFiles:
- src: css/app.sass
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.stylesDir %>app.sass
overwrite: true
- src: css/iconFont.css
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.stylesDir %>iconFont.css
overwrite: true
- condition: <%= buildCSS.sourceFormat === 'stylus' %>
templateFiles:
- src: css/app.styl
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.stylesDir %>app.styl
overwrite: true
- src: css/iconFont.css
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + paths.input.stylesDir %>iconFont.css
overwrite: true
- condition: <%= testVisualRegression.enabled === true %>
templateFiles:
- src: visualTest/*
dest: <%- paths.input.srcDir + resources.sampleApp.demoDir + testVisualRegression.moduleTestDir %>
overwrite: true
noParse: true
# The SampleApp build tool needs to know what the entrypoint file name is.
cssSourceFormat:
css:
entryPointFileNames:
- app.css
sass:
entryPointFileNames:
- app.sass
stylus:
entryPointFileNames:
- app.styl
# Server - Development
serverDev:
defaults:
port: 3000
hostname: localhost
protocol: https
serverProd:
defaults:
port: 3000
hostname: localhost
protocol: https
testSystem: {}
testUnit:
defaults:
testFramework: jasmine
testFrameworks:
- jasmine
- mocha
configModules:
- condition: <%- buildJS.framework.indexOf('AngularJS 1.x') > -1 %>
<<:
- condition: <%- buildJS.framework.indexOf('AngularJS 2.x') > -1 %>
<<:
- condition: <%- buildJS.framework.indexOf('React (latest)') > -1 %>
<<:
testVisualRegression: {}
verify:
verifyTasks: ['verify:js', 'verify:css']
configModules:
- packages: # Common tools
- <<:
- <<: *pkg_babel-eslint # We may not need this in the near future. ESLint can parse ES6 & ES7 things
- <<: *pkg_eslint-friendly-formatter
templateFiles:
- src: eslintignore.yml.tpl
dest: .eslintignore
overwrite: true
- src: .eslintrc.js.tpl
dest: <%= paths.config.configDir + resources.verify.configSubDir %>.eslintrc.js
overwrite: true
- condition: <%- verify.jsCodingStandard === 'AirBnB' %>
packages:
- <<: *pkg_eslint-config-airbnb
- <<: *pkg_eslint-plugin-import
- <<: *pkg_eslint-plugin-react
- <<: *pkg_eslint-plugin-jsx-a11y
- condition: <%- verify.jsCodingStandard === 'Google' %>
packages:
- <<: *pkg_eslint-config-google
- condition: <%- verify.jsCodingStandard === 'StandardJS' %>
packages:
- <<: *pkg_eslint-config-standard
- <<: *pkg_eslint-plugin-standard
- <<: *pkg_eslint-plugin-promise
- <<: *pkg_eslint-plugin-import
- <<: *pkg_eslint-plugin-node
- condition: <%- verify.jsCodingStandard === 'TypeScript' %>
packages:
- <<:
templateFiles:
- src: tslint.json
dest: <%= paths.config.configDir + resources.verify.configSubDir %>tslint.json
- condition: <%- buildCSS.sourceFormat === 'sass' %>
# No packages to install, as the build-tools will have their own
templateFiles:
- src: sasslint.yml
dest: <%= paths.config.configDir + resources.verify.configSubDir %>sasslint.yml
- condition: <%- buildCSS.sourceFormat === 'stylus' %>
# No packages to install, as the build-tools will have their own
templateFiles:
- src: stylintrc
dest: <%= paths.config.configDir + resources.verify.configSubDir %>.stylintrc
zzfinish:
# For browser projects, after installation, start the project
onEnd:
- cmd: npm
args: ['start']