"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const colorette_1 = require("colorette"); const webpack_cli_1 = require("webpack-cli"); const log_symbols_1 = __importDefault(require("log-symbols")); const path_1 = __importDefault(require("path")); const scaffold_utils_1 = require("./utils/scaffold-utils"); const utils_1 = require("./utils"); const types_1 = require("./types"); const { logger, getPackageManager } = webpack_cli_1.utils; /** * * Generator for initializing a webpack config * * @class InitGenerator * @extends CustomGenerator * @returns {Void} After execution, transforms are triggered * */ class InitGenerator extends types_1.CustomGenerator { constructor(args, opts) { super(args, opts); this.autoGenerateConfig = opts.autoSetDefaults; this.generationPath = opts.generationPath; this.dependencies = ['webpack', 'webpack-cli', 'babel-plugin-syntax-dynamic-import']; this.configuration = { config: { configName: 'config', topScope: [], webpackOptions: { mode: "'production'", entry: undefined, output: undefined, plugins: [], module: { rules: [], }, }, }, }; this.entryOption = './src/index.js'; this.configuration.config.topScope.push("const path = require('path');", "const webpack = require('webpack');", '\n'); this.configuration.config.webpackOptions.plugins.push('new webpack.ProgressPlugin()'); } async prompting() { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; logger.log(`${log_symbols_1.default.info}${colorette_1.blue(' INFO ')} ` + 'For more information and a detailed description of each question, have a look at: ' + `${colorette_1.bold(colorette_1.green('https://github.com/webpack/webpack-cli/blob/master/INIT.md'))}`); logger.log(`${log_symbols_1.default.info}${colorette_1.blue(' INFO ')} ` + 'Alternatively, run "webpack(-cli) --help" for usage info\n'); const { multiEntries } = await scaffold_utils_1.Confirm(self, 'multiEntries', 'Will your application have multiple bundles?', false, this.autoGenerateConfig); const entryOption = await utils_1.entryQuestions(self, multiEntries, this.autoGenerateConfig); if (typeof entryOption === 'string') { // single entry apply when default is not used if (entryOption.length > 0 && entryOption !== "'./src/index.js'") { this.configuration.config.webpackOptions.entry = entryOption; } } else if (typeof entryOption === 'object') { // multiple entries this.configuration.config.webpackOptions.entry = entryOption; } this.entryOption = entryOption; const { outputDir } = await scaffold_utils_1.Input(self, 'outputDir', 'In which folder do you want to store your generated bundles?', 'dist', this.autoGenerateConfig); // only apply when output dir is not default if (outputDir !== 'dist') { this.configuration.config.webpackOptions.output = { path: `path.resolve(__dirname, '${outputDir}')`, }; } const { langType } = await scaffold_utils_1.List(self, 'langType', 'Will you use one of the below JS solutions?', ['No', utils_1.LangType.ES6, utils_1.LangType.Typescript], 'No', this.autoGenerateConfig); utils_1.langQuestionHandler(this, langType); this.langType = langType; const { stylingType } = await scaffold_utils_1.List(self, 'stylingType', 'Will you use one of the below CSS solutions?', ['No', utils_1.StylingType.CSS, utils_1.StylingType.SASS, utils_1.StylingType.LESS, utils_1.StylingType.PostCSS], 'No', this.autoGenerateConfig); const { ExtractUseProps, regExpForStyles } = utils_1.styleQuestionHandler(self, stylingType); if (regExpForStyles) { // Ask if the user wants to use extractPlugin const { useExtractPlugin } = await scaffold_utils_1.Confirm(self, 'useExtractPlugin', 'Will you bundle your CSS files with MiniCssExtractPlugin?', false, this.autoGenerateConfig); if (useExtractPlugin) { const { cssBundleName } = await scaffold_utils_1.Input(self, 'cssBundleName', 'What will you name the CSS bundle?', 'main', this.autoGenerateConfig); this.dependencies.push('mini-css-extract-plugin'); this.configuration.config.topScope.push(utils_1.tooltip.cssPlugin(), "const MiniCssExtractPlugin = require('mini-css-extract-plugin');", '\n'); if (cssBundleName.length !== 0) { this.configuration.config.webpackOptions.plugins.push(`new MiniCssExtractPlugin({ filename:'${cssBundleName}.[contenthash].css' })`); } else { this.configuration.config.webpackOptions.plugins.push("new MiniCssExtractPlugin({ filename:'style.css' })"); } // Remove style-loader from the loader chain ExtractUseProps.shift(); ExtractUseProps.unshift({ loader: 'MiniCssExtractPlugin.loader', }); } // load CSS assets, with or without mini-css-extract-plugin this.configuration.config.webpackOptions.module.rules.push({ test: regExpForStyles, use: ExtractUseProps, }); } // webpack Dev Server const { useDevServer } = await scaffold_utils_1.Confirm(self, 'useDevServer', 'Do you want to use webpack-dev-server?', true, this.autoGenerateConfig); if (useDevServer) { this.dependencies.push('webpack-dev-server'); this.configuration.config.webpackOptions.devServer = { open: true, host: "'localhost'", }; } const { useHTMLPlugin } = await scaffold_utils_1.Confirm(self, 'useHTMLPlugin', 'Do you want to simplify the creation of HTML files for your bundle?', false, this.autoGenerateConfig); if (useHTMLPlugin) { // Html webpack Plugin this.dependencies.push('html-webpack-plugin'); const htmlWebpackDependency = 'html-webpack-plugin'; this.configuration.config.topScope.push(`const HtmlWebpackPlugin = require('${htmlWebpackDependency}')`, '\n', utils_1.tooltip.html()); this.configuration.config.webpackOptions.plugins.push(`new HtmlWebpackPlugin({ template: 'index.html' })`); } const { useWorkboxPlugin } = await scaffold_utils_1.Confirm(self, 'useWorkboxPlugin', 'Do you want to add PWA support?', true, this.autoGenerateConfig); // webpack Dev Server if (useWorkboxPlugin) { this.configuration.config.topScope.push("const WorkboxWebpackPlugin = require('workbox-webpack-plugin');", '\n'); this.dependencies.push('workbox-webpack-plugin'); this.configuration.config.webpackOptions.plugins.push(`new WorkboxWebpackPlugin.GenerateSW({ swDest: 'sw.js', clientsClaim: true, skipWaiting: false, })`); } this.configuration.config.webpackOptions.mode = this.autoGenerateConfig ? "'production'" : "'development'"; } installPlugins() { const packager = getPackageManager(); const opts = packager === 'yarn' ? { dev: true } : { 'save-dev': true }; this.scheduleInstallTask(packager, this.dependencies, opts, { cwd: this.generationPath }); } writing() { this.config.set('configuration', this.configuration); const packageJsonTemplatePath = '../init-template/package.json.js'; // eslint-disable-next-line @typescript-eslint/no-var-requires this.fs.extendJSON(this.destinationPath('package.json'), require(packageJsonTemplatePath)(this.autoGenerateConfig)); const generateEntryFile = (entryPath, name) => { entryPath = entryPath.replace(/'/g, ''); this.fs.copyTpl(path_1.default.resolve(__dirname, '../init-template/index.js'), this.destinationPath(entryPath), { name }); }; // Generate entry file/files const entry = this.configuration.config.webpackOptions.entry || './src/index.js'; if (typeof entry === 'string') { generateEntryFile(entry, 'your main file!'); } else if (typeof entry === 'object') { Object.keys(entry).forEach((name) => generateEntryFile(entry[name], `${name} main file!`)); } // Generate README this.fs.copyTpl(path_1.default.resolve(__dirname, '../init-template/README.md'), this.destinationPath('README.md'), {}); // Generate HTML template file this.fs.copyTpl(path_1.default.resolve(__dirname, '../init-template/template.html'), this.destinationPath('index.html'), {}); if (this.langType === utils_1.LangType.ES6) { this.fs.copyTpl(path_1.default.resolve(__dirname, '../init-template/.babelrc'), this.destinationPath('.babelrc'), {}); } else if (this.langType === utils_1.LangType.Typescript) { // Generate tsconfig const tsConfigTemplatePath = '../init-template/tsconfig.json.js'; // eslint-disable-next-line @typescript-eslint/no-var-requires this.fs.extendJSON(this.destinationPath('tsconfig.json'), require(tsConfigTemplatePath)); } } } exports.default = InitGenerator;