Skip to content

Commit

Permalink
cli(init): webpack4 ready (#356)
Browse files Browse the repository at this point in the history
* cli(init): webpack4 ready

* cli(init): remove unused variable, still @next on etwp

* cli(init): Allow to use default entry in `init`

* cli(init): Fix typo in comment

* cli(init): Optimization transform and tests

* cli(init): Fix non-optimized option for splitChunks

* cli(init): Add cachingGroup per entry, don't show name in prod

* cli(init): Add cachingGroup's defaults, fix entry

* cli(init): Add a link to where the defaults live

* cli(init): Remove default caching group definition from example
  • Loading branch information
EugeneHlushko authored and evenstensberg committed Apr 15, 2018
1 parent c94888d commit 3bbd428
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 38 deletions.
45 changes: 25 additions & 20 deletions lib/generators/init-generator.js
Expand Up @@ -4,9 +4,6 @@ const Generator = require("yeoman-generator");
const chalk = require("chalk");
const logSymbols = require("log-symbols");

const createCommonsChunkPlugin = require("webpack-addons")
.createCommonsChunkPlugin;

const Input = require("webpack-addons").Input;
const Confirm = require("webpack-addons").Confirm;
const List = require("webpack-addons").List;
Expand Down Expand Up @@ -43,7 +40,6 @@ module.exports = class InitGenerator extends Generator {
prompting() {
const done = this.async();
const self = this;
let oneOrMoreEntries;
let regExpForStyles;
let ExtractUseProps;
let outputPath = "dist";
Expand Down Expand Up @@ -83,9 +79,9 @@ module.exports = class InitGenerator extends Generator {
return entryQuestions(self, entryTypeAnswer);
})
.then(entryOptions => {
this.configuration.config.webpackOptions.entry = entryOptions;
oneOrMoreEntries = Object.keys(entryOptions);

if (entryOptions !== "\"\"") {
this.configuration.config.webpackOptions.entry = entryOptions;
}
return this.prompt([
Input(
"outputType",
Expand All @@ -94,8 +90,9 @@ module.exports = class InitGenerator extends Generator {
]);
})
.then(outputTypeAnswer => {
if (!this.configuration.config.webpackOptions.entry.length) {
this.configuration.config.topScope.push(tooltip.commonsChunk());
// 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) {
this.configuration.config.webpackOptions.output = {
filename: "'[name].[chunkhash].js'",
chunkFilename: "'[name].[chunkhash].js'"
Expand All @@ -117,8 +114,7 @@ module.exports = class InitGenerator extends Generator {
})
.then(prodConfirmAnswer => {
this.isProd = prodConfirmAnswer["prodConfirm"];
this.configuration.config.webpackOptions.mode =
this.isProd ? `"${"production"}"` : `"${"development"}"`;
this.configuration.config.webpackOptions.mode = this.isProd ? "'production'" : "'development'";
})
.then(() => {
return this.prompt([
Expand Down Expand Up @@ -378,15 +374,24 @@ module.exports = class InitGenerator extends Generator {
);
}
}
})
.then(() => {
if (this.configuration.config.webpackOptions.entry.length === 0) {
oneOrMoreEntries.forEach(prop => {
this.configuration.config.webpackOptions.plugins.push(
createCommonsChunkPlugin(prop)
);
});
}
// add splitChunks options for transparency
// defaults coming from: https://webpack.js.org/plugins/split-chunks-plugin/#optimization-splitchunks
this.configuration.config.topScope.push(tooltip.splitChunks());
this.configuration.config.webpackOptions.optimization = {
splitChunks: {
chunks: "'async'",
minSize: 30000,
minChunks: 1,
// for production name is recommended to be off
name: !this.isProd,
cacheGroups: {
vendors: {
test: "/[\\\\/]node_modules[\\\\/]/",
priority: -10
},
}
}
};
done();
});
}
Expand Down
23 changes: 11 additions & 12 deletions lib/generators/utils/entry.js
Expand Up @@ -20,7 +20,7 @@ module.exports = (self, answer) => {
.prompt([
InputValidate(
"multipleEntries",
"Type the names you want for your modules (entry files), separated by comma [example: 'app,vendor']",
"Type the names you want for your modules (entry files), separated by comma [example: app,vendor]",
validate
)
])
Expand All @@ -36,11 +36,11 @@ module.exports = (self, answer) => {
if (
n[val].charAt(0) !== "(" &&
n[val].charAt(0) !== "[" &&
n[val].indexOf("function") < 0 &&
n[val].indexOf("path") < 0 &&
n[val].indexOf("process") < 0
!n[val].includes("function") &&
!n[val].includes("path") &&
!n[val].includes("process")
) {
n[val] = `"${n[val]}.js"`;
n[val] = `"'${n[val]}.js'"`;
}
webpackEntryPoint[val] = n[val];
});
Expand All @@ -55,7 +55,7 @@ module.exports = (self, answer) => {
self.prompt([
InputValidate(
`${entryProp}`,
`What is the location of "${entryProp}"? [example: "./src/${entryProp}"]`,
`What is the location of "${entryProp}"? [example: ./src/${entryProp}]`,
validate
)
])
Expand All @@ -64,11 +64,11 @@ module.exports = (self, answer) => {
if (
propAns[val].charAt(0) !== "(" &&
propAns[val].charAt(0) !== "[" &&
propAns[val].indexOf("function") < 0 &&
propAns[val].indexOf("path") < 0 &&
propAns[val].indexOf("process") < 0
!propAns[val].includes("function") &&
!propAns[val].includes("path") &&
!propAns[val].includes("process")
) {
propAns[val] = `"${propAns[val]}.js"`;
propAns[val] = `"'${propAns[val]}.js'"`;
}
webpackEntryPoint[val] = propAns[val];
});
Expand All @@ -80,8 +80,7 @@ module.exports = (self, answer) => {
.prompt([
InputValidate(
"singularEntry",
"Which module will be the first to enter the application? [example: './src/index']",
validate
"Which module will be the first to enter the application? [default: ./src/index]"
)
])
.then(singularAnswer => `"${singularAnswer["singularEntry"]}"`);
Expand Down
14 changes: 9 additions & 5 deletions lib/generators/utils/tooltip.js
Expand Up @@ -17,13 +17,17 @@ module.exports = {
*
*/`;
},
commonsChunk: _ => {
splitChunks: _ => {
return `/*
* We've enabled commonsChunkPlugin for you. This allows your app to
* load faster and it splits the modules you provided as entries across
* different bundles!
* SplitChunksPlugin is enabled by default and replaced
* deprecated CommonsChunkPlugin. It automatically identifies modules which
* should be splitted of chunk by heuristics using module duplication count and
* module category (i. e. node_modules). And splits the chunks…
*
* https://webpack.js.org/plugins/commons-chunk-plugin/
* It is safe to remove "splitChunks" from the generated configuration
* and was added as an educational example.
*
* https://webpack.js.org/plugins/split-chunks-plugin/
*
*/`;
},
Expand Down
4 changes: 3 additions & 1 deletion lib/init/index.js
Expand Up @@ -34,6 +34,7 @@ const topScopeTransform = require("./transformations/top-scope/top-scope");
const devServerTransform = require("./transformations/devServer/devServer");
const modeTransform = require("./transformations/mode/mode");
const resolveLoaderTransform = require("./transformations/resolveLoader/resolveLoader");
const optimizationTransform = require("./transformations/optimization/optimization");

const transformsObject = {
entryTransform,
Expand Down Expand Up @@ -62,7 +63,8 @@ const transformsObject = {
recordsInputPathTransform,
recordsOutputPathTransform,
recordsPathTransform,
resolveLoaderTransform
resolveLoaderTransform,
optimizationTransform
};

/**
Expand Down
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`optimization transforms correctly using "optimization-0" data 1`] = `
"module.exports = {
entry: 'index.js',
output: {
filename: 'bundle.js'
},
optimization: {
splitChunks: {
minSize: 1,
chunks: 'all'
}
}
}
"
`;
@@ -0,0 +1,6 @@
module.exports = {
entry: 'index.js',
output: {
filename: 'bundle.js'
}
}
53 changes: 53 additions & 0 deletions lib/init/transformations/optimization/optimization.js
@@ -0,0 +1,53 @@
"use strict";

const utils = require("../../../utils/ast-utils");

/**
*
* Transform for optimization. Finds the optimization property from yeoman and creates a
* property based on what the user has given us.
*
* @param j — jscodeshift API
* @param ast - jscodeshift API
* @param {any} webpackProperties - transformation object to scaffold
* @param {String} action - action that indicates what to be done to the AST
* @returns ast - jscodeshift API
*/

module.exports = function profileTransform(j, ast, webpackProperties, action) {
function createProfileProperty(p) {
utils.pushCreateProperty(j, p, "optimization", j.objectExpression([]));
return utils.pushObjectKeys(j, p, webpackProperties, "optimization");
}

if (webpackProperties || typeof webpackProperties === "boolean") {
if (action === "init" && typeof webpackProperties === "object") {
return ast
.find(j.ObjectExpression)
.filter(p => utils.isAssignment(null, p, createProfileProperty));
} else if (
action === "init" &&
(webpackProperties.length || typeof webpackProperties === "boolean")
) {
return ast
.find(j.ObjectExpression)
.filter(p =>
utils.isAssignment(
j,
p,
utils.pushCreateProperty,
"optimization",
webpackProperties
)
);
} else if (action === "add") {
// TODO
} else if (action === "remove") {
// TODO
} else if (action === "update") {
// TODO
}
} else {
return ast;
}
};
16 changes: 16 additions & 0 deletions lib/init/transformations/optimization/optimization.test.js
@@ -0,0 +1,16 @@
"use strict";

const defineTest = require("../../../utils/defineTest");

defineTest(
__dirname,
"optimization",
"optimization-0",
{
splitChunks: {
minSize: 1,
chunks: "'all'"
}
},
"init"
);

0 comments on commit 3bbd428

Please sign in to comment.