UNPKG

10up-toolkit

Version:

Collection of reusable scripts for 10up development.

229 lines (211 loc) 7.13 kB
const CopyWebpackPlugin = require('copy-webpack-plugin'); const ESLintPlugin = require('eslint-webpack-plugin'); const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin'); const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); const StyleLintPlugin = require('stylelint-webpack-plugin'); const WebpackBar = require('webpackbar'); const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); const { resolve } = require('path'); const { VanillaExtractPlugin } = require('@vanilla-extract/webpack-plugin'); const RemoveEmptyScriptsPlugin = require('./plugins/remove-empty-scripts'); const CleanExtractedDeps = require('./plugins/clean-extracted-deps'); const TenUpToolkitTscPlugin = require('./plugins/tsc'); const NoBrowserSyncPlugin = require('./plugins/no-browser-sync'); const { hasStylelintConfig, fromConfigRoot, hasProjectFile, getArgFromCLI, transformBlockJson, } = require('../../utils'); const { isPackageInstalled } = require('../../utils/package'); const removeDistFolder = (file) => { return file.replace(/(^\.\/dist\/)|^dist\//, ''); }; // There are differences between Windows and Posix when it comes to the WebpackBar // This ensures that the same reporter is used everywhere const webpackbarArguments = process.env.JEST_WORKER_ID !== undefined ? { reporters: ['basic'] } : undefined; module.exports = ({ isPackage, isModule = false, isProduction, projectConfig: { devServer, filenames, devURL, devServerPort, paths, wpDependencyExternals, analyze, hot, useBlockAssets, }, packageConfig: { style }, buildFiles, }) => { const hasReactFastRefresh = hot && !isProduction && !isModule; const shouldCompileVanillaExtract = isPackageInstalled('@vanilla-extract/css'); const hasBrowserSync = isPackageInstalled('browser-sync-webpack-plugin') && isPackageInstalled('browser-sync'); const shouldLoadBrowserSync = !isProduction && devURL && !hasReactFastRefresh && hasBrowserSync; let browserSync = !isProduction && devURL ? new NoBrowserSyncPlugin() : false; if (shouldLoadBrowserSync) { // eslint-disable-next-line global-require, import/no-extraneous-dependencies const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); browserSync = new BrowserSyncPlugin( { host: 'localhost', port: getArgFromCLI('--port') || 3000, proxy: devURL, open: false, files: ['**/*.php', '**/*.js', 'dist/**/*.css'], ignore: ['dist/**/*.php', 'dist/**/*.js'], serveStatic: ['.'], rewriteRules: [ { match: /wp-content\/themes\/.*\/dist/g, replace: 'dist', }, ], }, { injectCss: true, reload: false, }, ); } const blocksSourceDirectory = resolve(process.cwd(), paths.blocksDir); return [ devServer && new HtmlWebpackPlugin({ ...(hasProjectFile('public/index.html') && { template: 'public/index.html' }), }), new ESLintPlugin({ failOnError: false, fix: false, lintDirtyModulesOnly: true, }), shouldCompileVanillaExtract && new VanillaExtractPlugin(), // MiniCSSExtractPlugin to extract the CSS that gets imported into JavaScript. new MiniCSSExtractPlugin({ filename: (options) => { if (isPackage) { return removeDistFolder(style); } let entryModules = []; try { // with the react fast refresh plugin // we cannot always assume there's a single entry module // so we need to check if any of the entry modules are relative to blocksSourceDirectory entryModules = options.chunk.getModules().filter((module) => { return module.isEntryModule(); }); } catch (e) { try { // if it failed it's bc there's only one entryModule entryModules.push(options.chunk.entryModule); } catch (e) { entryModules = []; } } let isBlockAsset = entryModules.some((module) => { const fullPath = module.resource; return fullPath ? !path .relative(blocksSourceDirectory, fullPath) // startWith('../') but in a cross-env way .startsWith(path.join('..', '/')) : false; }); if (!isBlockAsset) { if (useBlockAssets) { isBlockAsset = // match windows and posix paths buildFiles[options.chunk.name].match(/\/blocks?\//) || buildFiles[options.chunk.name].match(/\\blocks?\\/); } else { isBlockAsset = options.chunk.name.match(/-block$/); } } return isBlockAsset ? filenames.blockCSS : filenames.css; }, chunkFilename: '[id].css', }), !isPackage && // Copy static assets to the `dist` folder. new CopyWebpackPlugin({ patterns: [ { from: '**/*.{jpg,jpeg,png,gif,webp,avif,ico,svg,eot,ttf,woff,woff2,otf}', to: '[path][name][ext]', noErrorOnMissing: true, context: path.resolve(process.cwd(), paths.copyAssetsDir), }, useBlockAssets && { from: path.join(blocksSourceDirectory, '**/block.json').replace(/\\/g, '/'), context: blocksSourceDirectory, noErrorOnMissing: true, to: 'blocks/[path][name][ext]', transform: (content, absoluteFilename) => { return transformBlockJson(content, absoluteFilename); }, }, useBlockAssets && { from: path.join(blocksSourceDirectory, '**/*.php').replace(/\\/g, '/'), context: blocksSourceDirectory, noErrorOnMissing: true, to: 'blocks/[path][name][ext]', }, hasReactFastRefresh && { from: fromConfigRoot('fast-refresh.php'), to: '[path][name][ext]', noErrorOnMissing: true, context: path.resolve(process.cwd(), '/dist'), }, ].filter(Boolean), }), devURL && browserSync, // Lint CSS. new StyleLintPlugin({ context: path.resolve(process.cwd(), paths.srcDir), files: '**/*.(s(c|a)ss|css)', allowEmptyInput: true, lintDirtyModulesOnly: true, failOnError: false, ...(!hasStylelintConfig() && { configFile: fromConfigRoot('stylelint.config.js'), }), }), // Fancy WebpackBar. !hasReactFastRefresh && new WebpackBar(webpackbarArguments), // dependencyExternals variable controls whether scripts' assets get // generated, and the default externals set. wpDependencyExternals && !isPackage && new DependencyExtractionWebpackPlugin({ injectPolyfill: false, requestToHandle: (request) => { if (request.includes('react-refresh/runtime')) { if (isModule) { return undefined; } return 'tenup-toolkit-react-refresh-runtime'; } return undefined; }, }), new CleanExtractedDeps(), new RemoveEmptyScriptsPlugin(), new TenUpToolkitTscPlugin(), analyze && isProduction && new BundleAnalyzerPlugin({ analyzerMode: 'static' }), hasReactFastRefresh && new ReactRefreshWebpackPlugin({ overlay: { sockHost: '127.0.0.1', sockProtocol: 'ws', sockPort: devServerPort }, exclude: [/node_module/, /outputCssLoader\.js/], }), ].filter(Boolean); };