diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 7dc38823cb..e0bd6ac2fb 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,6 +2,7 @@ - [Project Structure](structure.md) - [Build Commands](commands.md) +- [Babel Configuration](babel.md) - [Linter Configuration](linter.md) - [Pre-Processors](pre-processors.md) - [Handling Static Assets](static.md) diff --git a/docs/babel.md b/docs/babel.md new file mode 100644 index 0000000000..eaa0ca9d83 --- /dev/null +++ b/docs/babel.md @@ -0,0 +1,22 @@ +# Babel Configuration + +This boilerplate uses [`babel-preset-env`](https://www.npmjs.com/package/babel-preset-env) for configuring babel. You can read more about it here - http://2ality.com/2017/02/babel-preset-env.html. + +> A Babel preset that compiles ES2015+ down to ES5 by automatically determining the Babel plugins and polyfills you need based on your targeted browser or runtime environments. + +It uses [`browserslist`](https://github.com/ai/browserslist) to parse this information, so we can use any [valid query format supported by `browserslist`](https://github.com/ai/browserslist#queries). + +However there is a caveat. `browserslist` recommends defining the target in a common place like `package.json` or in a `.browserslistrc` config file. This allows tools like [`autoprefixer`](https://github.com/postcss/autoprefixer) and [`eslint-plugin-compat`](https://github.com/amilajack/eslint-plugin-compat) to share the config. For this template, `browserslist` is configured in the `package.json`: + +```json +{ + "...": "...", + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} +``` + +But the latest stable release of `babel-preset-env`, `v1.6.1` does not support loading the config from `package.json`. So the target environment is repeated in `.babelrc`. If you wish to change your target environment, please be sure to update both `package.json` and `.babelrc`. Note that this has been fixed in the beta version([`@babel/preset-env@7.0.0-beta.34`](https://github.com/babel/babel/tree/master/packages/babel-preset-env)) and the template will be updated once it is out of beta. diff --git a/docs/structure.md b/docs/structure.md index 33bec21d84..75c958a42f 100644 --- a/docs/structure.md +++ b/docs/structure.md @@ -31,7 +31,7 @@ ├── .babelrc # babel config ├── .editorconfig # indentation, spaces/tabs and similar settings for your editor ├── .eslintrc.js # eslint config -├── .eslintignore.js # eslint ignore rules +├── .eslintignore # eslint ignore rules ├── .gitignore # sensible defaults for gitignore ├── .postcssrc.js # postcss config ├── index.html # index.html template diff --git a/meta.js b/meta.js index ed7a8b6a2d..1e0b798e20 100644 --- a/meta.js +++ b/meta.js @@ -1,18 +1,15 @@ const path = require('path'); const fs = require('fs'); - -function sortObject(object) { - // Based on https://github.com/yarnpkg/yarn/blob/v1.3.2/src/config.js#L79-L85 - const sortedObject = {}; - Object.keys(object).sort().forEach(item => { - sortedObject[item] = object[item]; - }); - return sortedObject; -} +const { + sortDependencies, + installDependencies, + runLintFix, + printMessage +} = require('./utils') module.exports = { - "helpers": { - "if_or": function (v1, v2, options) { + helpers: { + if_or: function (v1, v2, options) { if (v1 || v2) { return options.fn(this); } @@ -20,127 +17,153 @@ module.exports = { return options.inverse(this); } }, - "prompts": { - "name": { - "type": "string", - "required": true, - "message": "Project name" + prompts: { + name: { + type: 'string', + required: true, + message: 'Project name' }, - "description": { - "type": "string", - "required": false, - "message": "Project description", - "default": "A Vue.js project" + description: { + type: 'string', + required: false, + message: 'Project description', + default: 'A Vue.js project' }, - "author": { - "type": "string", - "message": "Author" + author: { + type: 'string', + message: 'Author' }, - "build": { - "type": "list", - "message": "Vue build", - "choices": [ + build: { + type: 'list', + message: 'Vue build', + choices: [ { - "name": "Runtime + Compiler: recommended for most users", - "value": "standalone", - "short": "standalone" + name: 'Runtime + Compiler: recommended for most users', + value: 'standalone', + short: 'standalone' }, { - "name": "Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere", - "value": "runtime", - "short": "runtime" + name: 'Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere', + value: 'runtime', + short: 'runtime' } ] }, - "router": { - "type": "confirm", - "message": "Install vue-router?" + router: { + type: 'confirm', + message: 'Install vue-router?' }, - "lint": { - "type": "confirm", - "message": "Use ESLint to lint your code?" + lint: { + type: 'confirm', + message: 'Use ESLint to lint your code?' }, - "lintConfig": { - "when": "lint", - "type": "list", - "message": "Pick an ESLint preset", - "choices": [ + lintConfig: { + when: 'lint', + type: 'list', + message: 'Pick an ESLint preset', + choices: [ { - "name": "Standard (https://github.com/standard/standard)", - "value": "standard", - "short": "Standard" + name: 'Standard (https://github.com/standard/standard)', + value: 'standard', + short: 'Standard' }, { - "name": "Airbnb (https://github.com/airbnb/javascript)", - "value": "airbnb", - "short": "Airbnb" + name: 'Airbnb (https://github.com/airbnb/javascript)', + value: 'airbnb', + short: 'Airbnb' }, { - "name": "none (configure it yourself)", - "value": "none", - "short": "none" + name: 'none (configure it yourself)', + value: 'none', + short: 'none' } ] }, - "unit": { - "type": "confirm", - "message": "Set up unit tests" + unit: { + type: 'confirm', + message: 'Set up unit tests' }, - "runner": { - "when": "unit", - "type": "list", - "message": "Pick a test runner", - "choices": [ + runner: { + when: 'unit', + type: 'list', + message: 'Pick a test runner', + choices: [ { - "name": "Jest", - "value": "jest", - "short": "jest" + name: 'Jest', + value: 'jest', + short: 'jest' }, { - "name": "Karma and Mocha", - "value": "karma", - "short": "karma" + name: 'Karma and Mocha', + value: 'karma', + short: 'karma' }, { - "name": "none (configure it yourself)", - "value": "noTest", - "short": "noTest" + name: 'none (configure it yourself)', + value: 'noTest', + short: 'noTest' } ] }, - "e2e": { - "type": "confirm", - "message": "Setup e2e tests with Nightwatch?" + e2e: { + type: 'confirm', + message: 'Setup e2e tests with Nightwatch?' + }, + autoInstall: { + type: 'list', + message: 'Should we run `npm install` for you after the project has been created? (recommended)', + choices: [ + { + name: 'Yes, use NPM', + value: 'npm', + short: 'npm' + }, + { + name: 'Yes, use Yarn', + value: 'yarn', + short: 'yarn' + }, + { + name: 'No, I will handle that myself', + value: false, + short: 'no' + } + ] } }, - "filters": { - ".eslintrc.js": "lint", - ".eslintignore": "lint", - "config/test.env.js": "unit || e2e", - "build/webpack.test.conf.js": "e2e || (unit && runner === 'karma')", - "test/unit/**/*": "unit", - "test/unit/index.js": "unit && runner === 'karma'", - "test/unit/jest.conf.js": "unit && runner === 'jest'", - "test/unit/karma.conf.js": "unit && runner === 'karma'", - "test/unit/specs/index.js": "unit && runner === 'karma'", - "test/unit/setup.js": "unit && runner === 'jest'", - "test/e2e/**/*": "e2e", - "src/router/**/*": "router" + filters: { + '.eslintrc.js': 'lint', + '.eslintignore': 'lint', + 'config/test.env.js': 'unit || e2e', + 'build/webpack.test.conf.js': "unit && runner === 'karma'", + 'test/unit/**/*': 'unit', + 'test/unit/index.js': "unit && runner === 'karma'", + 'test/unit/jest.conf.js': "unit && runner === 'jest'", + 'test/unit/karma.conf.js': "unit && runner === 'karma'", + 'test/unit/specs/index.js': "unit && runner === 'karma'", + 'test/unit/setup.js': "unit && runner === 'jest'", + 'test/e2e/**/*': 'e2e', + 'src/router/**/*': 'router' }, - "complete": function (data) { - const packageJsonFile = path.join( - data.inPlace ? "" : data.destDirName, - "package.json" - ); - const packageJson = JSON.parse(fs.readFileSync(packageJsonFile)); - packageJson.devDependencies = sortObject(packageJson.devDependencies); - packageJson.dependencies = sortObject(packageJson.dependencies); - fs.writeFileSync( - packageJsonFile, - JSON.stringify(packageJson, null, 2) + "\n" - ); + 'complete': function (data, { chalk }) { + + const green = chalk.green - const message = `To get started:\n\n ${data.inPlace ? '' : `cd ${data.destDirName}\n `}npm install\n npm run dev\n\nDocumentation can be found at https://vuejs-templates.github.io/webpack`; - console.log("\n" + message.split(/\r?\n/g).map(line => " " + line).join("\n")); + sortDependencies(data, green) + + const cwd = path.join(process.cwd(), data.inPlace ? '' : data.destDirName) + + if (data.autoInstall) { + installDependencies(cwd, data.autoInstall, green) + .then(() => { + return runLintFix(cwd, data, green) + }) + .then(() => { + printMessage(data, green) + }) + } else { + printMessage(data, chalk) + } + } }; diff --git a/package.json b/package.json index 09951adace..a00df3c157 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-cli-template-webpack", - "version": "1.2.5", + "version": "1.2.6", "license": "MIT", "description": "A full-featured Webpack setup with hot-reload, lint-on-save, unit testing & css extraction.", "scripts": { diff --git a/template/.babelrc b/template/.babelrc index 6e0aaac99c..6646ce7f96 100644 --- a/template/.babelrc +++ b/template/.babelrc @@ -1,16 +1,19 @@ { "presets": [ ["env", { - "modules": false + "modules": false, + "targets": { + "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] + } }], "stage-2" ], - "plugins": ["transform-runtime"]{{#if_or unit e2e}}, + "plugins": ["transform-vue-jsx", "transform-runtime"]{{#if_or unit e2e}}, "env": { "test": { "presets": ["env", "stage-2"]{{#if_eq runner "karma"}}, - "plugins": ["istanbul"]{{/if_eq}}{{#if_eq runner "jest"}}, - "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"]{{/if_eq}} + "plugins": ["transform-vue-jsx", "istanbul"]{{/if_eq}}{{#if_eq runner "jest"}}, + "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]{{/if_eq}} } }{{/if_or}} } diff --git a/template/.eslintrc.js b/template/.eslintrc.js index 8e8be20e8d..8624b369c5 100644 --- a/template/.eslintrc.js +++ b/template/.eslintrc.js @@ -42,6 +42,16 @@ module.exports = { js: 'never', vue: 'never' }], + // disallow reassignment of function parameters + // disallow parameter object manipulation except for specific exclusions + 'no-param-reassign': ['error', { + props: true, + ignorePropertyModificationsFor: [ + 'state', // for vuex state + 'acc', // for reduce accumulators + 'e' // for e.returnvalue + ] + }], // allow optionalDependencies 'import/no-extraneous-dependencies': ['error', { optionalDependencies: ['test/unit/index.js'] diff --git a/template/build/webpack.prod.conf.js b/template/build/webpack.prod.conf.js index d121faed35..bf613e8424 100644 --- a/template/build/webpack.prod.conf.js +++ b/template/build/webpack.prod.conf.js @@ -46,10 +46,11 @@ const webpackConfig = merge(baseWebpackConfig, { // extract css into its own file new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), - // set the following option to `true` if you want to extract CSS from - // codesplit chunks into this main css file as well. - // This will result in *all* of your app's CSS being loaded upfront. - allChunks: false, + // Setting the following option to `false` will not extract CSS from codesplit chunks. + // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. + // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, + // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 + allChunks: true, }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. diff --git a/template/config/index.js b/template/config/index.js index 0a7cfb43e1..05c69c1620 100644 --- a/template/config/index.js +++ b/template/config/index.js @@ -1,5 +1,5 @@ 'use strict' -// Template version: 1.2.5 +// Template version: 1.2.6 // see http://vuejs-templates.github.io/webpack for documentation. const path = require('path') diff --git a/template/package.json b/template/package.json index 23ffeb6ccc..e4e637e1d5 100644 --- a/template/package.json +++ b/template/package.json @@ -84,8 +84,11 @@ {{/e2e}} "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", + "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-loader": "^7.1.1", + "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.22.0", + "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", diff --git a/template/src/App.vue b/template/src/App.vue index 2ef72e8cbc..03d5e7247d 100644 --- a/template/src/App.vue +++ b/template/src/App.vue @@ -11,15 +11,15 @@