Skip to content

Commit

Permalink
cli(init): Refactor Yeoman (#323)
Browse files Browse the repository at this point in the history
* misc(refactor): refactoring work on init

* misc(refactor): refactor init

* misc(refactor): refactor init

* chore(deps): remove redundant dep

* misc(jsdocs): change occuring comment

* cli(init): move transform method to func

* misc(init): revise wrong expression

* misc(appveyor): only report bundlesize in travis

* misc(comment): add comment to indicate future replacement

* misc(lint): fix linting errors
  • Loading branch information
evenstensberg authored Mar 9, 2018
1 parent 8011b5a commit 6e9cb5f
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 443 deletions.
1 change: 0 additions & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ test_script:
- which npm
- npm run appveyor:lint
- npm run appveyor:test
- npm run bundlesize

cache:
- node_modules -> appveyor.yml,package.json,package-lock.json
6 changes: 5 additions & 1 deletion lib/generators/init-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ module.exports = class InitGenerator extends Generator {
if (regExpForStyles) {
if (this.isProd) {
this.configuration.config.topScope.push(tooltip.cssPlugin());
this.dependencies.push("extract-text-webpack-plugin");
// TODO: Replace with regular version once v.4 is out
this.dependencies.push("extract-text-webpack-plugin@next");

if (cssBundleName.length !== 0) {
this.configuration.config.webpackOptions.plugins.push(
Expand Down Expand Up @@ -410,4 +411,7 @@ module.exports = class InitGenerator extends Generator {
});
});
}
writing() {
this.config.set("configuration", this.configuration);
}
};
206 changes: 157 additions & 49 deletions lib/init/index.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,173 @@
"use strict";

const yeoman = require("yeoman-environment");
const Generator = require("yeoman-generator");
const path = require("path");
const defaultGenerator = require("../generators/init-generator");
const runTransform = require("./transformations/index");
const j = require("jscodeshift");
const chalk = require("chalk");
const pEachSeries = require("p-each-series");

const runPrettier = require("../utils/run-prettier");

const entryTransform = require("./transformations/entry/entry");
const outputTransform = require("./transformations/output/output");
const contextTransform = require("./transformations/context/context");
const resolveTransform = require("./transformations/resolve/resolve");
const devtoolTransform = require("./transformations/devtool/devtool");
const targetTransform = require("./transformations/target/target");
const watchTransform = require("./transformations/watch/watch");
const watchOptionsTransform = require("./transformations/watch/watchOptions");
const externalsTransform = require("./transformations/externals/externals");
const nodeTransform = require("./transformations/node/node");
const performanceTransform = require("./transformations/performance/performance");
const statsTransform = require("./transformations/stats/stats");
const amdTransform = require("./transformations/other/amd");
const bailTransform = require("./transformations/other/bail");
const cacheTransform = require("./transformations/other/cache");
const profileTransform = require("./transformations/other/profile");
const mergeTransform = require("./transformations/other/merge");
const parallelismTransform = require("./transformations/other/parallelism");
const recordsInputPathTransform = require("./transformations/other/recordsInputPath");
const recordsOutputPathTransform = require("./transformations/other/recordsOutputPath");
const recordsPathTransform = require("./transformations/other/recordsPath");
const moduleTransform = require("./transformations/module/module");
const pluginsTransform = require("./transformations/plugins/plugins");
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 transformsObject = {
entryTransform,
outputTransform,
contextTransform,
resolveTransform,
devtoolTransform,
targetTransform,
watchTransform,
watchOptionsTransform,
externalsTransform,
nodeTransform,
performanceTransform,
statsTransform,
amdTransform,
bailTransform,
cacheTransform,
profileTransform,
moduleTransform,
pluginsTransform,
topScopeTransform,
mergeTransform,
devServerTransform,
modeTransform,
parallelismTransform,
recordsInputPathTransform,
recordsOutputPathTransform,
recordsPathTransform,
resolveLoaderTransform
};

/**
*
* Runs yeoman and runs the transformations based on the object
* built up from an author/user
* Maps back transforms that needs to be run using the configuration
* provided.
*
* @param {String} options - An path to the given generator
* @returns {Function} runTransform - Run transformations based on the finished
* yeoman instance
* @param {Object} transformObject - An Object with all transformations
* @param {Object} config - Configuration to transform
* @returns {Object} - An Object with the transformations to be run
*/

function creator(options) {
let env = yeoman.createEnv("webpack", null);
const generatorName = options
? replaceGeneratorName(path.basename(options[0]))
: "webpack-default-generator";
if (options) {
const WebpackGenerator = class extends Generator {
initializing() {
options.forEach(path => {
return this.composeWith(require.resolve(path));
});
function mapOptionsToTransform(transformObject, config) {
return Object.keys(transformObject)
.map(transformKey => {
const stringVal = transformKey.substr(
0,
transformKey.indexOf("Transform")
);
if (Object.keys(config.webpackOptions).length) {
if (config.webpackOptions[stringVal]) {
return [
transformObject[transformKey],
config.webpackOptions[stringVal]
];
} else {
return [transformObject[transformKey], config[stringVal]];
}
} else {
return [transformObject[transformKey]];
}
};
env.registerStub(WebpackGenerator, generatorName);
} else {
env.registerStub(defaultGenerator, "webpack-default-generator");
}
})
.filter(e => e[1]);
}

env.run(generatorName).on("end", _ => {
if (generatorName !== "webpack-default-generator") {
//HACK / FIXME
env = env.options.env;
return runTransform(env.configuration);
} else {
return runTransform(env.getArgument("configuration"));
}
/**
*
* Runs the transformations from an object we get from yeoman
*
* @param {Object} webpackProperties - Configuration to transform
* @param {String} action - Action to be done on the given ast
* @returns {Promise} - A promise that writes each transform, runs prettier
* and writes the file
*/

module.exports = function runTransform(webpackProperties, action) {
// webpackOptions.name sent to nameTransform if match
const webpackConfig = Object.keys(webpackProperties).filter(p => {
return p !== "configFile" && p !== "configPath";
});
}
const initActionNotDefined = action && action !== "init" ? true : false;

/*
* @function replaceGeneratorName
*
* Replaces the webpack-addons pattern with the end of the addons name merged
* with 'generator'
*
* @param { String } name - name of the generator
* @returns { String } name - replaced pattern of the name
*/
webpackConfig.forEach(scaffoldPiece => {
const config = webpackProperties[scaffoldPiece];
const transformations = mapOptionsToTransform(transformsObject, config);
const ast = j(
initActionNotDefined
? webpackProperties.configFile
: "module.exports = {}"
);
const transformAction = action || null;

function replaceGeneratorName(name) {
return name.replace(/(webpack-addons)?([^:]+)(:.*)?/g, "generator$2");
}
return pEachSeries(transformations, f => {
if (!f[1]) {
return f[0](j, ast, transformAction);
} else {
return f[0](j, ast, f[1], transformAction);
}
})
.then(_ => {
let configurationName;
if (!config.configName) {
configurationName = "webpack.config.js";
} else {
configurationName = "webpack." + config.configName + ".js";
}

module.exports = {
creator,
replaceGeneratorName
const outputPath = initActionNotDefined
? webpackProperties.configPath
: path.join(process.cwd(), configurationName);
const source = ast.toSource({
quote: "single"
});

runPrettier(outputPath, source);
})
.catch(err => {
console.error(err.message ? err.message : err);
});
});
if (initActionNotDefined && webpackProperties.config.item) {
process.stdout.write(
"\n" +
chalk.green(
`Congratulations! ${
webpackProperties.config.item
} has been ${action}ed!\n`
)
);
} else {
process.stdout.write(
"\n" +
chalk.green(
"Congratulations! Your new webpack configuration file has been created!\n"
)
);
}
};
10 changes: 0 additions & 10 deletions lib/init/index.test.js

This file was deleted.

Loading

0 comments on commit 6e9cb5f

Please sign in to comment.