dn-middleware-webpack5
Version:
--- group: middleware name: webpack5 title: Webpack5 ---
134 lines (125 loc) • 5.58 kB
text/typescript
import * as path from "path";
import * as Dawn from "@dawnjs/types";
import type { Configuration } from "webpack/types.d";
import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
import { FileInfo, IGetWebpackConfigOpts } from "./types";
import getModule from "./dev-utils/getModule";
import getPlugins from "./dev-utils/getPlugins";
import { getPublicPath } from "./dev-utils/utils";
import getOptimization from "./dev-utils/getOptimization";
const moduleFileExtensions = [".js", ".mjs", ".json", ".jsx"];
// Generate webpack entries
const getEntry = (options: IGetWebpackConfigOpts) => {
const webpackEntry: any = {};
// const hotClientEntry = require.resolve("react-dev-utils/webpackHotDevClient");
(options.entry as FileInfo[]).forEach(({ name, file }) => {
webpackEntry[name] = [...options.inject, file, ...options.append];
if (options.hot) {
webpackEntry[name].unshift(`webpack-hot-middleware/client?reload=true&log=false&name=${name}`); // 热更新添加对应patch
}
});
return webpackEntry;
};
// Generate devtool/sourcemap
const getDevtool = (devtool: boolean | string, ctx: Dawn.Context) => {
let formatDevtool: string | false;
switch (devtool) {
case false:
formatDevtool = false;
break;
case true:
case undefined:
default:
if (typeof devtool === "string") {
formatDevtool = devtool;
} else {
formatDevtool = ctx.isEnvDevelopment ? "eval-cheap-module-source-map" : "cheap-source-map";
}
break;
}
return formatDevtool;
};
// Generate webpack config
export const getWebpackConfig = async (options: IGetWebpackConfigOpts, ctx: Dawn.Context) => {
// util symbol
ctx.isEnvDevelopment = options.env === "development";
ctx.isEnvProduction = options.env === "production";
const webpackModule = await getModule(options, ctx);
const config: Configuration = {
// Learn more about the mode configuration and what optimizations take place on each value.
// https://webpack.js.org/configuration/mode/
mode: options.env,
// stop compilation early in production
bail: ctx.isEnvProduction,
// https://webpack.js.org/configuration/devtool/#devtool
devtool: getDevtool(options.devtool, ctx),
// webpack can compile for multiple environments or targets.
// to understand what a target is in detail: https://webpack.js.org/concepts/targets/
target: options.target,
// web script entry(ies)
entry: getEntry(options),
output: {
// Add /* filename */ comments to generated require()s in the output.
pathinfo: ctx.isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: path.join(options?.folders?.script ?? "", "[name].js"),
// There are also additional JS chunk files if you use code splitting.
chunkFilename: path.join(options?.folders?.script ?? "", "[name].[chunkhash:8].chunk.js"),
// webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: getPublicPath(ctx),
// this defaults to 'window', but by setting it to 'this' then
// module chunks which are built will work in web workers as well.
globalObject: "this",
// User output option
...(options.output as any),
// The build folder.
path: path.resolve(options.cwd, (options.output as any)?.path),
},
module: webpackModule,
plugins: getPlugins(options, ctx).filter(Boolean),
resolve: {
alias: {
// Allows for better profiling with ReactDevTools
...(options.profiling && {
"react-dom$": "react-dom/profiling",
// This is a package for cooperative scheduling in a browser environment.
// It is currently used internally by React, but we plan to make it more generic.
// https://www.npmjs.com/package/scheduler
"scheduler/tracing": "scheduler/tracing-profiling",
}),
...options.alias,
},
// Enable resolving symlinks to the original location.
symlinks: true,
modules: [
"node_modules",
path.resolve(ctx.cwd, "./node_modules/"),
path.resolve(__dirname, "../node_modules/"),
ctx.cwd,
path.resolve(__dirname, "../"),
],
extensions: moduleFileExtensions.concat(ctx.useTypeScript ? [".ts", ".tsx", ".d.ts"] : []),
mainFields: ["module", "jsnext:main", "browser", "main"],
// Use tsconfig.paths as webpack alias
plugins: [ctx.useTypeScript && new TsconfigPathsPlugin()].filter(Boolean),
},
externals: options.externals as any,
// Some libraries import Node modules but don't use them in the browser.
// Tell webpack to provide empty mocks for them so importing them works.
// webpack@v5 make some changes, see: https://webpack.js.org/migrate/5/#test-webpack-5-compatibility
node: {
// TODO: node
},
// Cache the generated webpack modules and chunks to improve build speed.
// https://webpack.js.org/configuration/other-options/#cache
cache: options.cache as any,
// These options allows you to control how webpack notifies you
// of assets and entry points that exceed a specific file limit.
performance: options.performanceConfig,
optimization: getOptimization(options, ctx) as any,
};
return config;
};