UNPKG

@knighttower/utility

Version:

UtilityJs is a utility library that provides a collection of utility functions for various tasks. The library is designed to be easy to use and covers the most common use cases.

225 lines (209 loc) 7.49 kB
const path = require('path'); const workingDir = process.cwd(); const TerserPlugin = require('terser-webpack-plugin'); const { targets, webpackFormats } = require(`${workingDir}/source-files.cjs`); const { getFlagValue } = require('./NodeHelpers.cjs'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const mode = getFlagValue('mode') ?? 'production'; const isProduction = mode === 'production'; const formats = webpackFormats ?? [ { type: 'umd', dir: 'umd', ext: 'js' }, { type: 'commonjs2', dir: 'cjs', ext: 'cjs' }, { type: 'window', dir: 'browser', ext: 'js' }, ]; const cssRulesUse = (isBundle) => { const use = [ { loader: 'css-loader', options: { importLoaders: 2, url: false, // Do not handle URLs in your CSS }, }, ]; if (!isBundle) { use.unshift(MiniCssExtractPlugin.loader); } else { use.unshift('style-loader'); } return use; }; const postCss = { loader: 'postcss-loader', options: { postcssOptions: { plugins: [require('autoprefixer'), isProduction ? require('cssnano') : false].filter( Boolean ), }, }, }; /** * Generates a Webpack configuration for a given library name and target. * * @param {string} entry - The file source. * @param {string} target - The target name. * @param {string} dir - The directory name. * @param {string} libraryTarget - The library target format. * @param {string} ext - The file extension. * @returns {Object} - The Webpack configuration. */ const getWebpackConfig = (config) => ({ mode: mode, entry: config.entry, resolve: { modules: [ 'node_modules', path.resolve(__dirname, 'src'), path.resolve(__dirname, `${workingDir}/src`), path.resolve(__dirname, `${workingDir}/node_modules`), ], extensions: ['.mjs', '.js', '.json', '.cjs'], }, plugins: (() => { if (config.bundle) { return []; } return [ new MiniCssExtractPlugin({ filename: config.exportName + '.css' || '[name].css', }), ]; })(), output: { path: path.resolve(__dirname, `${workingDir}/dist/${config.dir}`), filename: `${config.exportName}.${config.ext}`, // library: config.exportName, // libraryTarget: config.libraryTarget, umdNamedDefine: true, // libraryExport: config.windowExport, globalObject: 'this', library: { name: config.exportName, type: config.libraryTarget, export: config.windowExport, umdNamedDefine: true, }, }, optimization: { minimize: isProduction ? true : false, minimizer: [ new TerserPlugin({ parallel: true, // exclude: [/cb\.js$/, /extra\.js$/], terserOptions: { // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions ecma: 6, // keep_classnames: true, // Preserve class names // keep_fnames: true, // Preserve function names // safari10: true, // Workaround for Safari 10/11 loop scoping and await bugs toplevel: true, output: { ascii_only: true, // Escape Unicode characters braces: true, // Always insert braces in if, for, do, while or with statements semicolons: true, // Separate statements with semicolons comments: false, }, compress: { arrows: true, // Enable arrow function compression (transform to function expressions) }, parse: { html5_comments: false, // Ignore HTML5 comments shebang: true, // Preserve shebang }, mangle: true, }, extractComments: false, // Do not extract comments to separate file }), ], }, stats: isProduction ? 'normal' : 'minimal', module: { rules: [ { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { targets: '> 0.5%, not dead, not ie 11', // Exclude IE11 & dead browsers useBuiltIns: 'usage', corejs: 3, modules: false, }, ], ], }, }, exclude: /node_modules/, }, { test: /\.css$/, use: [...cssRulesUse(config.bundle), postCss], }, { test: /\.scss$/, use: [ ...cssRulesUse(config.bundle), postCss, // Make sure postcss.config.js is configured with your desired plugins { loader: 'sass-loader', options: { sassOptions: { quietDeps: true, implementation: require('sass'), // Ensure Dart Sass is used }, }, }, ], }, ], }, }); /** * Extracts the file name without extension from a path if it ends with '.js'. * @param {string} path - The file path. * @returns {string|null} The file name without extension or null if not a '.js' file. */ function extractFileName(path) { const match = /([^\/]+)\.(js|css|sass|cjs|mjs|scss)$/.exec(path); return match ? match[1] : path; } // Generate multiple configurations function getAllConfigs() { const configs = []; targets.forEach((target) => { const isArray = Array.isArray(target.file); const fileName = isArray ? 'bundle' : extractFileName(target.file); // Generate multiple configurations for (const format of formats) { const exportName = target.exportName ?? fileName; const entry = (() => { if (isArray) { return { [exportName]: target.file.map((file) => `${workingDir}/src/${file}`), }; } return `${workingDir}/src/${target.file}`; })(); configs.push( getWebpackConfig({ entry, fileName, libraryTarget: format.type, dir: format.dir, ext: format.ext, exportName: exportName, windowExport: target.windowExport ?? undefined, bundle: target.bundle ?? false, }) ); } }); return configs; } const configs = getAllConfigs(); module.exports = configs;