UNPKG

@lark-project/cli

Version:

飞书项目插件开发工具

522 lines (521 loc) 27.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getWebpackConfigForReact = void 0; const path_1 = __importDefault(require("path")); const webpack_1 = __importDefault(require("webpack")); const html_webpack_plugin_1 = __importDefault(require("html-webpack-plugin")); const case_sensitive_paths_webpack_plugin_1 = __importDefault(require("case-sensitive-paths-webpack-plugin")); const terser_webpack_plugin_1 = __importDefault(require("terser-webpack-plugin")); const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin")); const css_minimizer_webpack_plugin_1 = __importDefault(require("css-minimizer-webpack-plugin")); const webpack_manifest_plugin_1 = require("webpack-manifest-plugin"); const webpackbar_1 = __importDefault(require("webpackbar")); // import InterpolateHtmlPlugin from 'react-dev-utils/InterpolateHtmlPlugin'; const getCSSModuleLocalIdent_1 = __importDefault(require("react-dev-utils/getCSSModuleLocalIdent")); const ModuleNotFoundPlugin_1 = __importDefault(require("react-dev-utils/ModuleNotFoundPlugin")); const react_refresh_webpack_plugin_1 = __importDefault(require("@pmmmwh/react-refresh-webpack-plugin")); const webpack_stats_plugin_1 = require("webpack-stats-plugin"); const constants_1 = require("../../../constants"); const paths_1 = require("../paths"); // style files regexes const cssRegex = /\.css$/; const cssModuleRegex = /\.module\.css$/; const sassRegex = /\.(scss|sass)$/; const sassModuleRegex = /\.module\.(scss|sass)$/; const lessRegex = /\.less$/; const lessModuleRegex = /\.module\.less$/; const presetEnvOptions = { targets: { browsers: ['firefox >= 52', 'chrome >= 67', 'safari >= 11', 'edge >= 25'], }, shippedProposals: true, }; function getStyleLoaders(cssOptions, preProcessor, options) { const { isEnvDevelopment, isEnvProduction } = options; const loaders = [ isEnvDevelopment && require.resolve('style-loader'), isEnvProduction && { loader: mini_css_extract_plugin_1.default.loader, // css is located in `static/css`, use '../../' to locate index.html folder // in production `paths.publicUrlOrPath` can be a relative path // options: paths.publicUrlOrPath.startsWith('.') ? { publicPath: '../../' } : {}, }, { loader: require.resolve('css-loader'), options: cssOptions, }, { // Options for PostCSS as we reference these options twice // Adds vendor prefixing based on your specified browser support in // package.json loader: require.resolve('postcss-loader'), options: { postcssOptions: { // Necessary for external CSS imports to work // https://github.com/facebook/create-react-app/issues/2677 ident: 'postcss', config: false, plugins: [ 'postcss-flexbugs-fixes', [ 'postcss-preset-env', { autoprefixer: { flexbox: 'no-2009', }, stage: 3, }, ], // Adds PostCSS Normalize as the reset css with default options, // so that it honors browserslist config in package.json // which in turn let's users customize the target behavior as per their needs. 'postcss-normalize', ], }, sourceMap: isEnvProduction ? false : isEnvDevelopment, }, }, ].filter(Boolean); if (preProcessor) { loaders.push({ loader: require.resolve('resolve-url-loader'), options: { sourceMap: isEnvProduction ? false : isEnvDevelopment, // root: paths.appSrc, }, }, { loader: require.resolve(preProcessor), options: { sourceMap: true, }, }); } return loaders; } function getWebpackConfigForReact({ key, webpackEnv, entry, generateHtmlTemplate, }) { const isEnvDevelopment = webpackEnv === 'development'; const isEnvProduction = webpackEnv === 'production'; // Variable used for enabling profiling in Production // passed into alias object. Uses a flag if passed into the build command const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile'); // We will provide `paths.publicUrlOrPath` to our app // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. // Get environment variables to inject into our app. // const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); const shouldUseReactRefresh = true; // env.raw.FAST_REFRESH; return { name: key, target: ['browserslist'], // Webpack noise constrained to errors and warnings stats: 'errors-warnings', mode: webpackEnv, // Stop compilation early in production bail: isEnvProduction, devtool: isEnvProduction ? false ? 'source-map' : false : isEnvDevelopment && 'cheap-module-source-map', // These are the "entry points" to our application. // This means they will be the "root" imports that are included in JS bundle. entry: { [key]: entry, }, output: { clean: true, // The build folder. path: path_1.default.join(paths_1.paths.appBuild, key), // There will be one main bundle, and one file per asynchronous chunk. // In development, it does not produce real files. filename: 'index.js', publicPath: isEnvProduction ? undefined : `/${key}/`, library: ['__MG_PLG_SHARED_MODULES__', '__MG_PLG_UI_ENTRY__'], libraryTarget: 'window', }, externals: { '@lark-project/ui-kit-plugin': ['__MG_PLG_SHARED_MODULES__', '__MG_PLG_COMPONENTS__'], '@lark-project/ui-kit-plugin/mobile': [ '__MG_PLG_SHARED_MODULES__', '__MG_PLG_COMPONENTS_MOBILE__', ], }, optimization: { minimize: isEnvProduction, minimizer: [ // This is only used in production mode new terser_webpack_plugin_1.default({ terserOptions: { parse: { // We want terser to parse ecma 8 code. However, we don't want it // to apply any minification steps that turns valid ecma 5 code // into invalid ecma 5 code. This is why the 'compress' and 'output' // sections only apply transformations that are ecma 5 safe // https://github.com/facebook/create-react-app/pull/4234 ecma: 2017, }, compress: { ecma: 5, // Disabled because of an issue with Uglify breaking seemingly valid code: // https://github.com/facebook/create-react-app/issues/2376 // Pending further investigation: // https://github.com/mishoo/UglifyJS2/issues/2011 comparisons: false, // Disabled because of an issue with Terser breaking valid code: // https://github.com/facebook/create-react-app/issues/5250 // Pending further investigation: // https://github.com/terser-js/terser/issues/120 inline: 2, }, mangle: { safari10: true, }, // Added for profiling in devtools keep_classnames: isEnvProductionProfile, keep_fnames: isEnvProductionProfile, output: { ecma: 5, comments: false, // Turned on because emoji and regex is not minified properly using default // https://github.com/facebook/create-react-app/issues/2488 ascii_only: true, }, }, extractComments: false, }), // This is only used in production mode new css_minimizer_webpack_plugin_1.default(), ], }, resolve: { // This allows you to set a fallback for where webpack should look for modules. // We placed these paths second because we want `node_modules` to "win" // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebook/create-react-app/issues/253 modules: ['node_modules'], // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: // https://github.com/facebook/create-react-app/issues/290 // `web` extension prefixes have been added for better support // for React Native Web. extensions: ['.mjs', '.js', '.ts', '.tsx', '.jsx', '.json'], plugins: [], }, module: { strictExportPresence: true, rules: [ // Handle node_modules packages that contain sourcemaps // shouldUseSourceMap && { // enforce: 'pre', // exclude: /@babel(?:\/|\\{1,2})runtime/, // test: /\.(js|mjs|jsx|ts|tsx|css)$/, // loader: require.resolve('source-map-loader'), // }, { // "oneOf" will traverse all following loaders until one will // match the requirements. When no loader matches it will fall // back to the "file" loader at the end of the loader list. oneOf: [ // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], type: 'asset', parser: { dataUrlCondition: { maxSize: constants_1.IMAGE_INLINE_MAX_SIZE, }, }, generator: { // publicPath: isEnvProduction ? undefined : `${key}/`, // outputPath: `${key}/`, }, }, { test: /\.svg$/, use: [ { loader: require.resolve('@svgr/webpack'), options: { prettier: false, svgo: false, svgoConfig: { plugins: [{ removeViewBox: false }], }, titleProp: true, ref: true, }, }, ], issuer: { and: [/\.(ts|tsx|js|jsx|md|mdx)$/], }, }, // Process application JS with Babel. // The preset includes JSX, Flow, TypeScript, and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, include: paths_1.paths.appSrc, loader: require.resolve('babel-loader'), options: { babelrc: false, configFile: false, presets: [ [require.resolve('@babel/preset-env'), presetEnvOptions], [require.resolve('@babel/preset-react'), { runtime: 'automatic' }], // 推荐tsconfig中配置 "jsx": "react-jsx" require.resolve('@babel/preset-typescript'), ], plugins: [ isEnvDevelopment && require.resolve('react-refresh/babel'), // fix: $RefreshReg$ is not defined https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/176 isEnvDevelopment && require.resolve('react-hot-loader/babel'), // [ // require.resolve('@babel/plugin-transform-modules-commonjs'), // { strictMode: false }, // ], // 移除'use strict' [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }], ].filter(Boolean), // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. // cacheDirectory: true, // See #6846 for context on why cacheCompression is disabled // cacheCompression: false, compact: isEnvProduction, }, }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. // "style" loader turns CSS into JS modules that inject <style> tags. // In production, we use MiniCSSExtractPlugin to extract that CSS // to a file, but in development "style" loader enables hot editing // of CSS. // By default we support CSS Modules with the extension .module.css { test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction ? false : isEnvDevelopment, modules: { mode: 'icss', }, }, undefined, { isEnvDevelopment, isEnvProduction, }), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. // Remove this when webpack adds a warning or an error for this. // See https://github.com/webpack/webpack/issues/6571 sideEffects: true, }, // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css { test: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction ? false : isEnvDevelopment, modules: { mode: 'local', getLocalIdent: getCSSModuleLocalIdent_1.default, }, }, undefined, { isEnvDevelopment, isEnvProduction, }), }, { test: lessRegex, exclude: lessModuleRegex, use: [ { loader: isEnvProduction ? mini_css_extract_plugin_1.default.loader : require.resolve('style-loader'), }, require.resolve('css-loader'), require.resolve('less-loader'), ], }, { test: lessModuleRegex, use: [ { loader: isEnvProduction ? mini_css_extract_plugin_1.default.loader : require.resolve('style-loader'), }, { loader: require.resolve('css-loader'), options: { modules: { localIdentName: 'module__[local]__[hash:base64]', }, }, }, require.resolve('less-loader'), ], }, // Opt-in support for SASS (using .scss or .sass extensions). // By default we support SASS Modules with the // extensions .module.scss or .module.sass { test: sassRegex, exclude: sassModuleRegex, use: getStyleLoaders({ importLoaders: 3, sourceMap: isEnvProduction ? false : isEnvDevelopment, modules: { mode: 'icss', }, }, 'sass-loader', { isEnvDevelopment, isEnvProduction, }), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. // Remove this when webpack adds a warning or an error for this. // See https://github.com/webpack/webpack/issues/6571 sideEffects: true, }, // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass { test: sassModuleRegex, use: getStyleLoaders({ importLoaders: 3, sourceMap: isEnvProduction ? false : isEnvDevelopment, modules: { mode: 'local', getLocalIdent: getCSSModuleLocalIdent_1.default, }, }, 'sass-loader', { isEnvDevelopment, isEnvProduction, }), }, // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. // This loader doesn't use a "test" so it will catch all modules // that fall through the other loaders. { // Exclude `js` files to keep "css" loader working as it injects // its runtime that would otherwise be processed through "file" loader. // Also exclude `html` and `json` extensions so they get processed // by webpacks internal loaders. exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/], type: 'asset/resource', }, // ** STOP ** Are you adding a new loader? // Make sure to add the new loader(s) before the "file" loader. ], }, ].filter(Boolean), }, plugins: [ new html_webpack_plugin_1.default(Object.assign({}, { inject: false, filename: 'index.html', templateContent: ({ htmlWebpackPlugin }) => { return generateHtmlTemplate(htmlWebpackPlugin.files.js, htmlWebpackPlugin.files.css); }, }, isEnvProduction ? { minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, } : undefined)), new ModuleNotFoundPlugin_1.default(paths_1.paths.appPath), // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`. // It is absolutely essential that NODE_ENV is set to production // during a production build. // Otherwise React will be compiled in the very slow development mode. // new webpack.DefinePlugin(env.stringified), // Experimental hot reloading for React . // https://github.com/facebook/react/tree/main/packages/react-refresh isEnvDevelopment && shouldUseReactRefresh && new react_refresh_webpack_plugin_1.default({ overlay: false, }), // Watcher doesn't work well if you mistype casing in a path so we use // a plugin that prints an error when you attempt to do this. // See https://github.com/facebook/create-react-app/issues/240 isEnvDevelopment && new case_sensitive_paths_webpack_plugin_1.default(), isEnvProduction && new mini_css_extract_plugin_1.default({ // Options similar to the same options in webpackOptions.output // both options are optional filename: '[name].[contenthash:8].css', chunkFilename: '[name].[contenthash:8].chunk.css', }), // Generate an asset manifest file with the following content: // - "files" key: Mapping of all asset filenames to their corresponding // output file so that tools can pick it up without having to parse // `index.html` // - "entrypoints" key: Array of files which are included in `index.html`, // can be used to reconstruct the HTML if necessary new webpack_manifest_plugin_1.WebpackManifestPlugin({ fileName: 'asset-manifest.json', generate: (seed, files, entrypoints) => { const manifestFiles = files.reduce((manifest, file) => { manifest[file.name] = file.path; return manifest; }, seed); return { resourceId: key, files: manifestFiles, entrypoints, }; }, }), // Moment.js is an extremely popular library that bundles large locale files // by default due to how webpack interprets its code. This is a practical // solution that requires the user to opt into importing specific locales. // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // You can remove this if you don't use Moment.js: new webpack_1.default.IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/, }), new webpackbar_1.default({ name: key, }), new webpack_stats_plugin_1.StatsWriterPlugin({ filename: 'stats.json', stats: { module: true, assets: false, children: false, chunkGroups: true, chunks: true, dependentModules: false, optimizationBailout: false, excludeModules: [/node_modules/], }, }), ].filter(Boolean), // Turn off performance processing because we utilize // our own hints via the FileSizeReporter performance: false, }; } exports.getWebpackConfigForReact = getWebpackConfigForReact;