UNPKG

@pega/constellation-dx-components-build-utils

Version:

This tool uses a 'v3' approach to group components in a library, create a component map, employ webpack, and load the library like Pega-generated components, constellation app-static.

201 lines (189 loc) 7.3 kB
const path = require('path'); const customDonePlugin = require('./plugins/CustomDonePlugin'); const dynamicFetchScriptHookPlugin = require('./plugins/DynamicFetchScriptHookPlugin'); const SourceMapDevToolPlugin = require('webpack').SourceMapDevToolPlugin; const webpack = require('webpack'); const { StatsWriterPlugin } = require('webpack-stats-plugin'); const CompressionPlugin = require('compression-webpack-plugin'); function short3CharId(input) { const parts = input.match(/[A-Z][a-z]+|[A-Za-z0-9]+/g) || []; const initials = parts.map(p => p[0]).join('').slice(0, 2); // 1–2 initials const hash = require("crypto") .createHash("md5").update(input).digest("hex").slice(0, 1); // 1 hex char return (initials + hash).padEnd(3, 'x'); // ensure 3 chars } const compressionBRConfObj = { filename: '[path][base].br', algorithm: 'brotliCompress', test: /\.(js|css|html|svg|png|jpg|woff|woff2)$/, compressionOptions: { level: 11 } }; const imageInlineSizeLimit = Number.parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || '10000', 10); module.exports = (env) => { return { mode: env.mode ? env.mode : 'production', entry: env.customCmptDir != 'undefined' ? './index.js' : './src/index.js', output: { path: env.customCmptDir != 'undefined' ? path.resolve(env.outputPath) : path.resolve(env.buildFolderFullPath), filename: (pathData) => { return env.mode === 'development' ? (pathData.chunk.name === 'main' ? 'index.js' : '[name].[contenthash:8].js') : 'componentsmap.js'; }, chunkFilename: env.v3 == 'true' ? short3CharId(env.buildFolderName) + env.packageVersion.replaceAll('.', '') + '_[name].[contenthash:8].js' : 'chunks/[name].[contenthash:8].js' }, devServer: { static: { directory: path.join(__dirname, 'dist'), }, compress: false, port: env.port, hot: true, open: false, allowedHosts: 'all', headers: { 'Access-Control-Allow-Origin': '*', // or specify your domain instead of '*' 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', 'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization', }, client: { webSocketURL: { hostname: 'localhost' }, } }, devtool: env.mode === 'development' ? 'eval-source-map' : 'source-map', module: { rules: [ { test: /\.(?:js|mjs|jsx|cjs|ts|tsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env', { targets: "defaults" }], ['@babel/preset-react', { runtime: "automatic" }], ['@babel/preset-typescript'] ] } } }, { test: /\.css$/i, use: ["style-loader", "css-loader"], }, { test: /\.s[ac]ss$/i, use: ["style-loader", "css-loader", "sass-loader"], }, { test: /\.(png|bmp|svg|jpe?g|gif)$/i, loader: 'url-loader', options: { limit: imageInlineSizeLimit, name: 'images/[name].[contenthash:4].[ext]', }, } ] }, plugins: [ ...((env.v3 === 'true' || env.mode === 'development') ? [] : [ new SourceMapDevToolPlugin({ append: '\n//# sourceMappingURL='+env.appStaticUrl+'/component/'+env.buildFolderName+':'+env.packageVersion+'/chunks/[url]?orgId='+env.orgId, filename: '[file].map[query]', })]), new customDonePlugin({ projectName: path.resolve(""), libName: env.buildFolderName, libVersion: env.packageVersion }), ...(env.mode === 'development' ? [] : ( env.v3 === 'true' ? [new dynamicFetchScriptHookPlugin(true)] : [new dynamicFetchScriptHookPlugin()] )), new webpack.ids.DeterministicChunkIdsPlugin({ maxLength:8 }), new webpack.IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/ }), /* Ignore cosmos icons */ new webpack.IgnorePlugin({ resourceRegExp: /^\.\/icons$/, contextRegExp: /@pega\/cosmos-react-core\/lib\/components\/Icon$/ }), /* Ignore cosmos icons - windows */ new webpack.IgnorePlugin({ resourceRegExp: /^\.\/icons$/, contextRegExp: /@pega\\cosmos-react-core\\lib\\components\\Icon$/ }), /* Ignore cosmos streamline-icons */ new webpack.IgnorePlugin({ resourceRegExp: /^\.\/streamline-icons$/, contextRegExp: /@pega\/cosmos-react-core\/lib\/components\/Icon$/ }), /* Ignore cosmos streamline-icons - windows */ new webpack.IgnorePlugin({ resourceRegExp: /^\.\/streamline-icons$/, contextRegExp: /@pega\\cosmos-react-core\\lib\\components\\Icon$/ }), /* cosmos 6.x and above */ new webpack.IgnorePlugin({ resourceRegExp: /^\.\/.*\/.*\.icon$/, contextRegExp: /@pega\/cosmos-react-core\/lib\/components\/Icon$/ }), /* Ignore cosmos icons - windows */ new webpack.IgnorePlugin({ resourceRegExp: /^\.\/.*\/.*\.icon$/, contextRegExp: /@pega\\cosmos-react-core\\lib\\components\\Icon$/ }), new CompressionPlugin(compressionBRConfObj), /* To generate Manifest */ /*new StatsWriterPlugin({ stats: { fields: ["assets"] }, filename: "stats.json", })*/ new StatsWriterPlugin({ filename: 'stats.json', stats: { assets: true, entrypoints: true, namedChunkGroups: true, chunks: true, // Omit if not needed modules: false, // This can be huge — include only if necessary performance: false, }, transform(data) { return JSON.stringify({ assets: (data.assets || []).filter(asset => !asset.name.endsWith('.map')).slice(0, 10000), entrypoints: data.entrypoints, namedChunkGroups: data.namedChunkGroups, }, null); }, }) ], externals: { "react": "React", "react-dom": "ReactDOM" }, resolve: { extensions: ['.ts', '.js', '.jsx', '.tsx'], fallback: { stream: require.resolve('stream-browserify'), os: require.resolve('os-browserify/browser'), perf_hooks: false, module: require.resolve("module"), path: require.resolve("path-browserify"), browser: require.resolve('os-browserify/browser'), "fs": false, "constants": require.resolve("constants-browserify") } }, optimization: env.mode === 'development' ? { splitChunks: false, runtimeChunk: false, } : { splitChunks: { chunks: 'all', minSize: 60000, // 60 KB maxSize: 300000, // 300 KB }, }, }; };