From 821c7535b029e40f6a3a6391d8dc9e0ef8990d21 Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Fri, 18 May 2018 21:21:33 +0200 Subject: [PATCH 1/8] cli(init): set default generator name --- packages/generators/utils/entry.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/generators/utils/entry.js b/packages/generators/utils/entry.js index 2da6f5bd2a5..b1d1a9eff20 100644 --- a/packages/generators/utils/entry.js +++ b/packages/generators/utils/entry.js @@ -87,8 +87,12 @@ module.exports = (self, answer) => { ]) .then(singularEntryAnswer => { let { singularEntry } = singularEntryAnswer; - if (singularEntry.indexOf("\"") >= 0) + if (singularEntry.indexOf("\"") >= 0) { singularEntry = singularEntry.replace(/"/g, "'"); + } + if (singularEntry.length <= 0) { + singularEntry = "'./src/index.js'"; + } return singularEntry; }); } From 8dcc4acea1e292e519020954605338519f825531 Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Fri, 18 May 2018 21:41:28 +0200 Subject: [PATCH 2/8] cli(init): better defaults --- packages/generators/init-generator.js | 25 +++++++++++++++++++++---- packages/generators/utils/entry.js | 2 +- packages/generators/utils/module.js | 7 +++++-- packages/utils/recursive-parser.js | 4 +++- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/generators/init-generator.js b/packages/generators/init-generator.js index 0f45e919f65..db41ed0f8a7 100644 --- a/packages/generators/init-generator.js +++ b/packages/generators/init-generator.js @@ -29,7 +29,14 @@ module.exports = class InitGenerator extends Generator { constructor(args, opts) { super(args, opts); this.isProd = false; - this.dependencies = ["webpack", "webpack-cli", "uglifyjs-webpack-plugin"]; + (this.usingDefaults = false), + (this.dependencies = [ + "webpack", + "webpack-cli", + "uglifyjs-webpack-plugin", + "babel-plugin-syntax-dynamic-import", + "path" + ]); this.configuration = { config: { webpackOptions: {}, @@ -93,12 +100,15 @@ module.exports = class InitGenerator extends Generator { .then(outputTypeAnswer => { // As entry is not required anymore and we dont set it to be an empty string or """"" // it can be undefined so falsy check is enough (vs entry.length); - if (!this.configuration.config.webpackOptions.entry) { + if ( + !this.configuration.config.webpackOptions.entry && + !this.usingDefaults + ) { this.configuration.config.webpackOptions.output = { filename: "'[name].[chunkhash].js'", chunkFilename: "'[name].[chunkhash].js'" }; - } else { + } else if (!this.usingDefaults) { this.configuration.config.webpackOptions.output = { filename: "'[name].[chunkhash].js'" }; @@ -106,7 +116,9 @@ module.exports = class InitGenerator extends Generator { if (outputTypeAnswer["outputType"].length) { outputPath = outputTypeAnswer["outputType"]; } - this.configuration.config.webpackOptions.output.path = `path.resolve(__dirname, '${outputPath}')`; + if (!this.usingDefaults) { + this.configuration.config.webpackOptions.output.path = `path.resolve(__dirname, '${outputPath}')`; + } }) .then(() => { return this.prompt([ @@ -394,9 +406,13 @@ module.exports = class InitGenerator extends Generator { done(); }); } + /* installPlugins() { const asyncNamePrompt = this.async(); const defaultName = this.isProd ? "prod" : "config"; + if(this.isProd) { + this.dependencies = this.dependencies.filter(p => p !== "uglifyjs-webpack-plugin"); + } this.prompt([ Input( "nameType", @@ -415,6 +431,7 @@ module.exports = class InitGenerator extends Generator { this.runInstall(packager, this.dependencies, opts); }); } + */ writing() { this.config.set("configuration", this.configuration); diff --git a/packages/generators/utils/entry.js b/packages/generators/utils/entry.js index b1d1a9eff20..6b1a246d4d0 100644 --- a/packages/generators/utils/entry.js +++ b/packages/generators/utils/entry.js @@ -91,7 +91,7 @@ module.exports = (self, answer) => { singularEntry = singularEntry.replace(/"/g, "'"); } if (singularEntry.length <= 0) { - singularEntry = "'./src/index.js'"; + self.usingDefaults = true; } return singularEntry; }); diff --git a/packages/generators/utils/module.js b/packages/generators/utils/module.js index 2b46c03881c..dcf36fda42a 100644 --- a/packages/generators/utils/module.js +++ b/packages/generators/utils/module.js @@ -10,10 +10,13 @@ module.exports = _ => { return { test: `${new RegExp(/\.js$/)}`, - exclude: "/node_modules/", + include: ["path.resolve(__dirname, 'src')"], loader: "'babel-loader'", options: { - presets: ["'env'"] + presets: ["'env'", { + modules: false + }], + plugins: ["'syntax-dynamic-import'"] } }; }; diff --git a/packages/utils/recursive-parser.js b/packages/utils/recursive-parser.js index 3d991175bec..6b6fa841539 100644 --- a/packages/utils/recursive-parser.js +++ b/packages/utils/recursive-parser.js @@ -36,7 +36,9 @@ module.exports = function recursiveTransform(j, ast, value, action, key) { } else if (key === "merge") { utils.parseMerge(j, p, value); } else { - utils.addProperty(j, p, key, value); + if (value) { + utils.addProperty(j, p, key, value); + } } }); } From cf8b1d5f09c096d6baffe24198a6c81f375473dd Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Sat, 19 May 2018 15:59:03 +0200 Subject: [PATCH 3/8] chore(rebase): remove old commit --- .appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4008bbd659d..c7b78dc9f79 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,7 +16,6 @@ install: - npm ci - npm install --global codecov - npm install eslint-plugin-node@latest --save-dev - - npm install eslint-plugin-prettier@latest --save-dev test_script: - node --version From b64f780596c1ad7cb8e0ab844e21fad9de400048 Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Sat, 19 May 2018 17:52:44 +0200 Subject: [PATCH 4/8] cli(init): fix broken ast and merge scaffolds --- packages/generators/init-generator.js | 16 ++++-- packages/utils/ast-utils.js | 82 ++++++++++++++++++++++++++- packages/utils/prop-types.js | 5 +- packages/utils/recursive-parser.js | 17 +++--- packages/utils/scaffold.js | 12 +++- 5 files changed, 112 insertions(+), 20 deletions(-) diff --git a/packages/generators/init-generator.js b/packages/generators/init-generator.js index db41ed0f8a7..87455fb974c 100644 --- a/packages/generators/init-generator.js +++ b/packages/generators/init-generator.js @@ -74,8 +74,6 @@ module.exports = class InitGenerator extends Generator { this.configuration.config.topScope.push( "const webpack = require('webpack')", "const path = require('path')", - tooltip.uglify(), - "const UglifyJSPlugin = require('uglifyjs-webpack-plugin');", "\n" ); @@ -406,12 +404,19 @@ module.exports = class InitGenerator extends Generator { done(); }); } - /* installPlugins() { const asyncNamePrompt = this.async(); const defaultName = this.isProd ? "prod" : "config"; - if(this.isProd) { - this.dependencies = this.dependencies.filter(p => p !== "uglifyjs-webpack-plugin"); + if (this.isProd) { + this.dependencies = this.dependencies.filter( + p => p !== "uglifyjs-webpack-plugin" + ); + } else { + this.configuration.config.topScope.push( + tooltip.uglify(), + "const UglifyJSPlugin = require('uglifyjs-webpack-plugin');", + "\n" + ); } this.prompt([ Input( @@ -431,7 +436,6 @@ module.exports = class InitGenerator extends Generator { this.runInstall(packager, this.dependencies, opts); }); } - */ writing() { this.config.set("configuration", this.configuration); diff --git a/packages/utils/ast-utils.js b/packages/utils/ast-utils.js index cfdd6ced81f..bc67093e0fb 100644 --- a/packages/utils/ast-utils.js +++ b/packages/utils/ast-utils.js @@ -429,6 +429,84 @@ function addProperty(j, p, key, value) { } return; } + +/** + * + * Get an property named topScope from yeoman and inject it to the top scope of + * the config, outside module.exports + * + * @param j — jscodeshift API + * @param ast - jscodeshift API + * @param {any} value - transformation object to scaffold + * @param {String} action - action that indicates what to be done to the AST + * @returns ast - jscodeshift API + */ + +function parseTopScope(j, ast, value, action) { + function createTopScopeProperty(p) { + value.forEach(n => { + if ( + !p.value.body[0].declarations || + n.indexOf(p.value.body[0].declarations[0].id.name) <= 0 + ) { + p.value.body.splice(-1, 0, n); + } + }); + } + if (value) { + return ast.find(j.Program).filter(p => createTopScopeProperty(p)); + } else { + return ast; + } +} + +("use strict"); + +/** + * + * Transform for merge. Finds the merge property from yeoman and creates a way + * for users to allow webpack-merge in their scaffold + * + * @param j — jscodeshift API + * @param ast - jscodeshift API + * @param {any} value - transformation object to scaffold + * @param {String} action - action that indicates what to be done to the AST + * @returns ast - jscodeshift API + */ + +function parseMerge(j, ast, value, action) { + function createMergeProperty(p) { + // FIXME Use j.callExp() + let exportsDecl = p.value.body.map(n => { + if (n.expression) { + return n.expression.right; + } + }); + const bodyLength = exportsDecl.length; + let newVal = {}; + newVal.type = "ExpressionStatement"; + newVal.expression = { + type: "AssignmentExpression", + operator: "=", + left: { + type: "MemberExpression", + computed: false, + object: j.identifier("module"), + property: j.identifier("exports") + }, + right: j.callExpression(j.identifier("merge"), [ + j.identifier(value), + exportsDecl.pop() + ]) + }; + p.value.body[bodyLength - 1] = newVal; + } + if (value) { + return ast.find(j.Program).filter(p => createMergeProperty(p)); + } else { + return ast; + } +} module.exports = { safeTraverse, createProperty, @@ -444,5 +522,7 @@ module.exports = { createIdentifierOrLiteral, findObjWithOneOfKeys, getRequire, - addProperty + addProperty, + parseTopScope, + parseMerge }; diff --git a/packages/utils/prop-types.js b/packages/utils/prop-types.js index 05b58ce2044..d7f9bfdd143 100644 --- a/packages/utils/prop-types.js +++ b/packages/utils/prop-types.js @@ -19,7 +19,7 @@ module.exports = new Set([ "module", "node", "output", - "optimizations", + "optimization", "parallelism", "performance", "plugins", @@ -33,5 +33,6 @@ module.exports = new Set([ "splitChunks", "target", "watch", - "watchOptions" + "watchOptions", + "topScope" ]); diff --git a/packages/utils/recursive-parser.js b/packages/utils/recursive-parser.js index 6b6fa841539..9cabad98b83 100644 --- a/packages/utils/recursive-parser.js +++ b/packages/utils/recursive-parser.js @@ -2,7 +2,12 @@ const utils = require("./ast-utils"); -module.exports = function recursiveTransform(j, ast, value, action, key) { +module.exports = function recursiveTransform(j, ast, key, value, action) { + if (key === "topScope") { + return utils.parseTopScope(j, ast, value, action); + } else if (key === "merge") { + return utils.parseMerge(j, ast, value, action); + } const node = utils.findRootNodesByName(j, ast, key); if (node.size() !== 0) { // push to existing key @@ -31,14 +36,8 @@ module.exports = function recursiveTransform(j, ast, value, action, key) { }) .filter(p => p.value.properties); return root.forEach(p => { - if (key === "topScope") { - utils.parseTopScope(j, p, value); - } else if (key === "merge") { - utils.parseMerge(j, p, value); - } else { - if (value) { - utils.addProperty(j, p, key, value); - } + if (value) { + utils.addProperty(j, p, key, value); } }); } diff --git a/packages/utils/scaffold.js b/packages/utils/scaffold.js index 8fcc6b93b5b..deb395a6142 100644 --- a/packages/utils/scaffold.js +++ b/packages/utils/scaffold.js @@ -43,15 +43,23 @@ module.exports = function runTransform(webpackProperties, action) { webpackConfig.forEach(scaffoldPiece => { const config = webpackProperties[scaffoldPiece]; const transformations = mapOptionsToTransform(config); + if (config.topScope) { + transformations.push("topScope"); + } + if (config.merge) { + transformations.push("merge"); + } const ast = j( initActionNotDefined ? webpackProperties.configFile : "module.exports = {}" ); const transformAction = action || null; - return pEachSeries(transformations, f => { - return astTransform(j, ast, config.webpackOptions[f], transformAction, f); + if (f === "merge" || f === "topScope") { + return astTransform(j, ast, f, config[f], transformAction); + } + return astTransform(j, ast, f, config.webpackOptions[f], transformAction); }) .then(_ => { let configurationName; From 359aef5bd7a7224cc9a2904ad53ed0cc5046dc7d Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Sat, 19 May 2018 18:08:44 +0200 Subject: [PATCH 5/8] chore(docs): better defaults --- INIT.md | 10 +------- packages/generators/init-generator.js | 33 +++++---------------------- 2 files changed, 7 insertions(+), 36 deletions(-) diff --git a/INIT.md b/INIT.md index 368c5c14c87..6c428e980c6 100644 --- a/INIT.md +++ b/INIT.md @@ -14,10 +14,6 @@ What we are meaning here, is if you want to provide your bundle a single or mult This answers to the output directory of your application. The output directory is where servers or your `index.html` will read the generated bundle from. -3. `Are you going to use this in production? (Y/n)` - -If you answer `Yes` to this, we add [`MinCssExtractPlugin`](https://github.com/webpack-contrib/mini-css-extract-plugin) to your project. This means that your style files will be separated in production from the bundles where they are used. If you answer `No`, we will not use the plugin, and `Question 6` will be ignored by default. - 4. `Will you be using ES2015? (Y/n)` If you answer `Yes` to this question, we will add [`ES2015`](https://babeljs.io/learn-es2015/) to your webpack configuration, which will allow you to use modern JavaScript in your project. @@ -29,8 +25,4 @@ If you use any sort of style in your project, such as [`.less`](http://lesscss.o 6. `If you want to bundle your CSS files, what will you name the bundle? (press enter to skip)` -If you answered `Yes` to `Question 3`, this will be enabled. The default value for your generated CSS file is `style.[contentHash].css`, which will collect all your `.less`, `.scss` or `.css` into one file. This will make your build faster in production. - -7. `Name your 'webpack.[name].js?' [default: 'prod/config']` - -If you answered `Yes` to `Question 3`, the default name of your configuration will be `webpack.prod.js`, otherwise it will be `webpack.config.js` if you don't answer. Other good options to answer to this question is: `dev`, `base`, `production` or `development`. +If you indicate based on previous questions that you are using production, this will be enabled. The default value for your generated CSS file is `style.[contentHash].css`, which will collect all your `.less`, `.scss` or `.css` into one file. This will make your build faster in production. diff --git a/packages/generators/init-generator.js b/packages/generators/init-generator.js index 87455fb974c..fa6ea495b89 100644 --- a/packages/generators/init-generator.js +++ b/packages/generators/init-generator.js @@ -119,17 +119,12 @@ module.exports = class InitGenerator extends Generator { } }) .then(() => { - return this.prompt([ - Confirm("prodConfirm", "Are you going to use this in production?") - ]); - }) - .then(prodConfirmAnswer => { - this.isProd = prodConfirmAnswer["prodConfirm"]; + console.log(this.usingDefaults); + this.isProd = this.usingDefaults ? true : false; + this.configuration.config.configName = this.isProd ? "prod" : "dev"; this.configuration.config.webpackOptions.mode = this.isProd ? "'production'" : "'development'"; - }) - .then(() => { return this.prompt([ Confirm("babelConfirm", "Will you be using ES2015?") ]); @@ -405,7 +400,6 @@ module.exports = class InitGenerator extends Generator { }); } installPlugins() { - const asyncNamePrompt = this.async(); const defaultName = this.isProd ? "prod" : "config"; if (this.isProd) { this.dependencies = this.dependencies.filter( @@ -418,25 +412,10 @@ module.exports = class InitGenerator extends Generator { "\n" ); } - this.prompt([ - Input( - "nameType", - `Name your 'webpack.[name].js?' [default: '${defaultName}']:` - ) - ]) - .then(nameTypeAnswer => { - this.configuration.config.configName = nameTypeAnswer["nameType"].length - ? nameTypeAnswer["nameType"] - : defaultName; - }) - .then(() => { - asyncNamePrompt(); - const packager = getPackageManager(); - const opts = packager === "yarn" ? { dev: true } : { "save-dev": true }; - this.runInstall(packager, this.dependencies, opts); - }); + const packager = getPackageManager(); + const opts = packager === "yarn" ? { dev: true } : { "save-dev": true }; + this.runInstall(packager, this.dependencies, opts); } - writing() { this.config.set("configuration", this.configuration); } From 52ca883eab9a9f0c24e2bc427619819eed3aa152 Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Sat, 19 May 2018 19:49:36 +0200 Subject: [PATCH 6/8] chore(lint): fix linting errors --- packages/generators/init-generator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/generators/init-generator.js b/packages/generators/init-generator.js index fa6ea495b89..1338272f936 100644 --- a/packages/generators/init-generator.js +++ b/packages/generators/init-generator.js @@ -400,7 +400,6 @@ module.exports = class InitGenerator extends Generator { }); } installPlugins() { - const defaultName = this.isProd ? "prod" : "config"; if (this.isProd) { this.dependencies = this.dependencies.filter( p => p !== "uglifyjs-webpack-plugin" From 3c5057c8dadea6b9e177306ca8de032e287b30fb Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Sun, 20 May 2018 16:14:48 +0200 Subject: [PATCH 7/8] chore(deps): remove path from dep installation --- packages/generators/init-generator.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/generators/init-generator.js b/packages/generators/init-generator.js index 1338272f936..03d2ccf3d1b 100644 --- a/packages/generators/init-generator.js +++ b/packages/generators/init-generator.js @@ -34,8 +34,7 @@ module.exports = class InitGenerator extends Generator { "webpack", "webpack-cli", "uglifyjs-webpack-plugin", - "babel-plugin-syntax-dynamic-import", - "path" + "babel-plugin-syntax-dynamic-import" ]); this.configuration = { config: { From 5fdb178f601452b6d72ac2b373b055ff2758a735 Mon Sep 17 00:00:00 2001 From: ev1stensberg Date: Sun, 20 May 2018 18:02:01 +0200 Subject: [PATCH 8/8] chore(resolve): resolve conflicts --- .appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index c7b78dc9f79..0bfa3c5e098 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,6 +16,8 @@ install: - npm ci - npm install --global codecov - npm install eslint-plugin-node@latest --save-dev + - npm install eslint-config-prettier@latest --save-dev + - npm install eslint-plugin-prettier@latest --save-dev test_script: - node --version