const { autoCssModulesHandler, esbuildLoader } = require('@umijs/mfsu'); const { chalk } = require('@umijs/utils'); const { ProvidePlugin } = require('../compiled/webpack'); const { MFSU_NAME } = require('../constants'); const { es5ImcompatibleVersionsToPkg, isMatch } = require('../utils/depMatch'); const { Env, Transpiler } = require('../types'); async function addJavaScriptRules(opts) { const { config, userConfig, cwd, name } = opts; const isDev = opts.env === Env.development; const useFastRefresh = isDev && userConfig.fastRefresh !== false && name !== MFSU_NAME; const depPkgs = Object.assign({}, es5ImcompatibleVersionsToPkg()); const srcRules = [ config.module .rule('src') .test(/\.(js|mjs)$/) .include.add([ cwd, // import module out of cwd using APP_ROOT // issue: https://github.com/umijs/umi/issues/5594 ...(process.env.APP_ROOT ? [process.cwd()] : []), ]) .end() .exclude.add(/node_modules/) .end(), config.module.rule('jsx-ts-tsx').test(/\.(jsx|ts|tsx)$/), config.module .rule('extra-src') .test(/\.(js|mjs)$/) .include.add(path => { try { // do src transform for bundler-webpack/client/client/client.js if (path.includes('client/client/client')) return true; return isMatch({ path, pkgs: depPkgs }); } catch (e) { console.error(chalk.red(e)); throw e; } }) .end(), ]; if (userConfig.mdx) { srcRules.push(config.module.rule('markdown').test(/\.mdx?$/)); } const depRules = [ config.module .rule('dep') .test(/\.(js|mjs)$/) .include.add(/node_modules/) .end() .exclude.add(path => { try { return isMatch({ path, pkgs: depPkgs }); } catch (e) { console.error(chalk.red(e)); throw e; } }) .end(), ]; // const prefix = existsSync(join(cwd, 'src')) ? join(cwd, 'src') : cwd; const srcTranspiler = userConfig.srcTranspiler || Transpiler.babel; srcRules.forEach(rule => { if (srcTranspiler === Transpiler.babel) { rule .use('babel-loader') .loader(require.resolve('../../compiled/babel-loader')) .options({ // Tell babel to guess the type, instead assuming all files are modules // https://github.com/webpack/webpack/issues/4039#issuecomment-419284940 sourceType: 'unambiguous', babelrc: false, cacheDirectory: false, // process.env.BABEL_CACHE !== 'none' // ? join(cwd, `.umi/.cache/babel-loader`) // : false, targets: userConfig.targets, presets: [ opts.babelPreset || [ require.resolve('@umijs/babel-preset-umi'), { presetEnv: {}, presetReact: {}, presetTypeScript: {}, pluginTransformRuntime: {}, pluginLockCoreJS: {}, pluginDynamicImportNode: false, pluginAutoCSSModules: userConfig.autoCSSModules, }, ], ...opts.extraBabelPresets, ...(userConfig.extraBabelPresets || []).filter(Boolean), ], plugins: [ useFastRefresh && require.resolve('react-refresh/babel'), ...opts.extraBabelPlugins, ...(userConfig.extraBabelPlugins || []), ].filter(Boolean), }); } else if (srcTranspiler === Transpiler.swc) { const AutoCSSModule = require('../swcPlugins/autoCSSModules').default; rule .use('swc-loader') .loader(require.resolve('../loader/swc')) .options({ plugin: m => new AutoCSSModule().visitProgram(m), }); } else if (srcTranspiler === Transpiler.esbuild) { rule .use('esbuild-loader') .loader(esbuildLoader) .options({ target: isDev ? 'esnext' : 'es2015', handler: [autoCssModulesHandler, ...opts.extraEsbuildLoaderHandler], }); // esbuild loader can not auto import `React` config.plugin('react-provide-plugin').use(ProvidePlugin, [ { React: 'react', }, ]); } else { throw new Error(`Unsupported srcTranspiler ${srcTranspiler}.`); } }); if (userConfig.mdx) { config.module .rule('mdx') .test(/\.mdx?$/) .use('mdx-loader') .loader(userConfig.mdx?.loader) .options(userConfig.mdx?.loaderOptions); } const depTranspiler = userConfig.depTranspiler || Transpiler.none; depRules.forEach(_rule => { if (depTranspiler === Transpiler.none) { // noop } else { throw new Error(`Unsupported depTranspiler ${depTranspiler}.`); } }); } module.exports = addJavaScriptRules;