UNPKG

flamingo-carotene-webpack

Version:

Provide an abstraction for webpack with the ability for other modules to extend the webpack config, with integration into the flamingo-carotene-dev-server module

253 lines (218 loc) 7.06 kB
const path = require('path') const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); const TerserPlugin = require("terser-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const { WebpackManifestPlugin } = require('webpack-manifest-plugin') const isProd = !process.env.NODE_ENV || process.env.NODE_ENV === 'production' class WebpackConfig { constructor(core) { this.config = core.getConfig() this.cliTools = core.getCliTools() } getCacheConfig () { if (process.env.NODE_ENV === 'development') { return { info: { // 'none' or 'test'. mode: 'none', // 'debug', 'log', 'info', 'warn', or 'error'. level: (this.cliTools.isVerbose() ? 'debug' : 'error'), }, // Clean up large, old caches automatically. cachePrune: { // Caches younger than `maxAge` are not considered for deletion. They must // be at least this (default: 2 days) old in milliseconds. maxAge: 2 * 24 * 60 * 60 * 1000, // All caches together must be larger than `sizeThreshold` before any // caches will be deleted. Together they must be at least this // (default: 50 MB) big in bytes. sizeThreshold: 50 * 1024 * 1024 } } } return null } getWebpackConfig () { let mode = isProd ? 'production' : 'development' if (this.cliTools.hasOption(['--forceDev'])) { mode = 'development' } const webpackConfig = { target: 'web', stats: 'verbose', // context: config.paths.src, mode: mode, entry: path.join(this.config.paths.webpack.src, 'index.js'), output: { path: this.config.paths.webpackDist, filename: this.getOutputFileName(), publicPath: this.config.webpack.publicPath || '/' }, resolve: { modules: [ this.config.paths.src, path.join(this.config.paths.project, 'node_modules') ] }, resolveLoader: { modules: [ this.config.paths.src, path.join(this.config.paths.project, 'node_modules') ] }, module: { rules: [ { test: /\.js$/, include: this.getRulesInclude(), use: this.getJsLoaders() }, { test: /\.(sa|sc|c)ss$/, include: this.getRulesInclude(), use: this.getStyleLoaders() }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, type: 'asset/resource' }, { test: /\.(woff|woff2|eot|ttf|otf)(\?.*)?$/, type: 'asset/resource' } ] }, optimization: { splitChunks: { cacheGroups: { commons: { test: /[\\/]node_modules[\\/]/, name: 'vendor', chunks: 'all', enforce: true } } }, minimize: (mode !== 'development'), minimizer: [ new CssMinimizerPlugin(), new TerserPlugin({ // cache: true, parallel: true, extractComments: (mode !== 'development'), terserOptions: { sourceMap: (mode === 'development'), // Compression specific options compress: { // Drop console statements drop_console: (mode !== 'development') }, keep_fnames: true // Needed for IE11 and behaviors - otherwise the IE cannot differentiate the behavior names } }), ] }, plugins: [ // See: https://webpack.js.org/plugins/mini-css-extract-plugin/ new MiniCssExtractPlugin({ filename: this.getCssFileName() }), new WebpackManifestPlugin() ] } if (!isProd) { webpackConfig['devtool'] = 'source-map' } if (this.cliTools.hasOption(['--analyzeBundle'])) { const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; webpackConfig.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'static', reportFilename: path.join(this.config.paths.project, 'webpackBundleAnalyze.html'), openAnalyzer: true })) } return webpackConfig } getOutputFileName () { let fileName = isProd ? '[name].[contenthash].js' : '[name].js' if (this.config.webpack.dist.jsFolderName) { fileName = path.join(this.config.webpack.dist.jsFolderName, fileName) } return fileName } getCssFileName () { let fileName = isProd ? '[name].[contenthash].css' : '[name].css' if (this.config.webpack.dist.cssFolderName) { fileName = path.posix.join(this.config.webpack.dist.cssFolderName, fileName) } return fileName } getFontFileName () { // For shorter hash: 'font/[name].[sha512:hash:base64:7].[ext]' let fileName = isProd ? '[name].[hash].[ext]' : '[name].[ext]' if (this.config.webpack.dist.fontFolderName) { fileName = path.posix.join(this.config.webpack.dist.fontFolderName, fileName) } return fileName } getImageFileName () { // For shorter hash: name: 'img/[name].[sha512:hash:base64:7].[ext]' let fileName = isProd ? '[name].[hash].[ext]' : '[name].[ext]' if (this.config.webpack.dist.imageFolderName) { fileName = path.posix.join(this.config.webpack.dist.imageFolderName, fileName) } return fileName } getRulesInclude () { const include = [path.posix.normalize(this.config.paths.src)] if (this.config.webpack.rulesInclude && Array.isArray(this.config.webpack.rulesInclude)) { // Concat the arrays and remove doubles return include.concat(this.config.webpack.rulesInclude).filter(function (value, index, self) { return self.indexOf(value) === index }) } return include } getJsLoaders () { return [ 'import-glob' ] } getStyleLoaders () { return [ { loader: MiniCssExtractPlugin.loader, options: this.getMiniCssExtractLoaderOptions() }, { loader: 'css-loader', options: {} }, { loader: 'sass-loader', options: { implementation: this.getSassImplementation(), sassOptions: { quietDeps: true, includePaths: [ path.join(this.config.paths.project, 'node_modules') ] } } }, ] } getSassImplementation() { return require('sass') } getMiniCssExtractLoaderOptions () { const pluginOptions = {} if (this.config.webpack.dist.cssFolderName) { const cssDirName = path.dirname(path.join(this.config.paths.dist, this.getCssFileName())) const relativeDistPath = path.relative(cssDirName, this.config.paths.dist) pluginOptions['publicPath'] = relativeDistPath + '/' } return pluginOptions } } module.exports = WebpackConfig