在使用Webpack v5进行项目的生产构建之后,产品组装中不需要的包将进入最终的捆绑包。例如typescript.
webpack.common config:
const DotenvPlugin = require('dotenv-webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const paths = require('./paths');
module.exports = {
context: paths.appPath,
entry: paths.appIndexJs,
output: {
path: paths.appBuild,
publicPath: paths.publicUrlOrPath,
},
resolve: {
alias: {
'core-js/es6': 'core-js/es',
},
modules: [paths.appNodeModules, paths.appSrc],
extensions: paths.moduleFileExtensions.map((extension) => `.${extension}`),
plugins: [new TsconfigPathsPlugin()],
fallback: { crypto: false },
},
devServer: {
host: process.env.HOST,
port: process.env.PORT,
compress: true,
allowedHosts: 'all',
},
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
include: paths.appSrc,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
cacheDirectory: true,
cacheCompression: false,
compact: false,
},
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: 'file-loader',
options: {
limit: 10000,
name: 'assets/[name].[contenthash:8].[ext]',
},
},
{
test: /\.(ttf|eot|woff|woff2|)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
},
},
},
{
test: /\.svg$/,
use: [
{
loader: require.resolve('@svgr/webpack'),
},
{
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'assets/[name].[contenthash:8].[ext]',
},
},
],
},
],
strictExportPresence: true,
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
favicon: paths.appFavicon,
}),
new DotenvPlugin({
path: paths.dotenv,
expand: true,
systemvars: true,
}),
],
};
webpack.prod config:
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const SentryWebpackPlugin = require('@sentry/webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const CompressionPlugin = require('compression-webpack-plugin');
const common = require('./webpack.common');
class DeleteSourceMapWebpackPlugin {
constructor() {}
apply(compiler) {
compiler.hooks.done.tap('DeleteSourceMapWebpackPlugin', (stats) => {
const fs = require('fs');
const path = require('path');
const directoryPath = path.join(__dirname, '../build/js/');
fs.readdir(directoryPath, (err, files) => {
console.log('files', files);
files
.filter((name) => /\.js\.map$/.test(name))
.forEach((file) => {
console.log('file', file);
fs.unlinkSync(directoryPath + file);
});
});
console.log('⭐⭐⭐deleted map file');
});
}
}
function makeRelease(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
module.exports = merge(common, {
mode: 'production',
bail: true,
devtool: false,
output: {
filename: 'js/[name].[contenthash:8].js',
chunkFilename: 'js/[name].[contenthash:8].chunk.js',
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
parse: {
ecma: 8,
},
compress: {
// ecma: 5,
ecma: 2015,
// warnings: false,
comparisons: false,
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
ascii_only: true,
},
},
}),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
map: false,
},
cssProcessorPluginOptions: {
preset: ['default', { minifyFontValues: { removeQuotes: false } }],
},
}),
],
splitChunks: {
chunks: 'all',
},
runtimeChunk: {
name: (entrypoint) => `runtime-${entrypoint.name}`,
},
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: false,
},
},
],
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: false,
},
},
],
},
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[name].[contenthash:8].chunk.css',
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
},
}),
new ForkTsCheckerWebpackPlugin({
async: false,
typescript: {
memoryLimit: 4096,
},
}),
new DeleteSourceMapWebpackPlugin(),
new BundleAnalyzerPlugin({
statsOptions: { source: false },
analyzerMode: process.env.STATS || 'disabled',
}),
new CompressionPlugin(),
],
});
my package.json:
{
"name": "eva",
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/runtime": "7.18.0",
"@fortawesome/fontawesome-svg-core": "6.1.0",
"@fortawesome/free-brands-svg-icons": "6.1.0",
"@fortawesome/free-regular-svg-icons": "6.1.0",
"@fortawesome/free-solid-svg-icons": "6.1.0",
"@fortawesome/react-fontawesome": "0.1.18",
"@icons/material": "0.4.1",
"@material-ui/core": "4.9.2",
"@material-ui/icons": "4.9.1",
"@react-leaflet/core": "1.1.1",
"@sentry/react": "^5.30.0",
"@sentry/tracing": "^5.30.0",
"@testing-library/react": "12.1.4",
"@types/uniqid": "^5.3.2",
"ansi-html-community": "0.0.8",
"axios": "0.26.1",
"bootstrap-4-grid": "3.3.0",
"chart.js": "3.7.1",
"chartjs-adapter-date-fns": "2.0.0",
"chartjs-plugin-datalabels": "2.0.0",
"classnames": "2.3.1",
"core-js": "3.21.1",
"cross-env": "7.0.3",
"date-fns": "2.28.0",
"dotenv": "16.0.0",
"es6-promise": "4.2.8",
"fast-memoize": "2.5.2",
"fs-extra": "10.0.1",
"hex-to-css-filter": "4.0.0",
"identity-obj-proxy": "3.0.0",
"leaflet": "1.7.1",
"leaflet-draw": "1.0.4",
"leaflet-fullscreen": "^1.0.2",
"leaflet-rotatedmarker": "0.2.0",
"leaflet-routing-machine": "3.2.12",
"leaflet.heat": "0.2.0",
"leaflet.markercluster": "1.5.3",
"match-sorter": "6.3.1",
"namor": "2.0.2",
"nouislider": "15.5.1",
"prop-types": "15.7.2",
"rc-progress": "3.2.4",
"rc-slider": "9.7.5",
"react": "16.8.6",
"react-addons-css-transition-group": "15.6.2",
"react-beautiful-dnd": "13.1.0",
"react-color": "2.19.3",
"react-contextmenu": "2.13.0",
"react-custom-scroll": "4.2.0",
"react-datepicker": "4.8.0",
"react-dev-utils": "10.2.1",
"react-dom": "16.8.6",
"react-google-maps-loader": "4.3.0",
"react-json-view": "1.21.3",
"react-leaflet": "^3.2.5",
"react-leaflet-draw": "^0.20.4",
"react-leaflet-fullscreen": "2.0.2",
"react-leaflet-markercluster": "1.1.8",
"react-leaflet-rotatedmarker": "0.1.0",
"react-loading-skeleton": "^3.2.1",
"react-medium-image-zoom": "4.3.0",
"react-redux": "7.1.3",
"react-router": "5.2.0",
"react-router-dom": "5.0.1",
"react-scripts": "5.0.0",
"react-select": "1.2.1",
"react-slider": "1.0.8",
"react-table": "7.7.0",
"react-table-hoc-fixed-columns": "2.3.0",
"react-table-v6": "6.8.6",
"react-text-mask": "5.4.3",
"react-tooltip": "4.2.21",
"react-transition-group": "4.4.1",
"react-virtualized-auto-sizer": "1.0.5",
"react-window": "1.8.6",
"react-yandex-maps": "4.5.0",
"reactjs-popup": "1.5.0",
"recharts": "1.8.5",
"redux": "4.0.4",
"redux-thunk": "2.3.0",
"resolve": "1.15.0",
"save": "2.4.0",
"semver": "6.3.0",
"sockjs-client": "1.5.2",
"text-mask-addons": "3.8.0",
"ts-pnp": "1.1.6",
"uniqid": "^5.4.0",
"use-leaflet": "1.6.1",
"warning": "4.0.3"
},
"devDependencies": {
"@babel/core": "7.18.0",
"@babel/plugin-transform-runtime": "7.18.0",
"@babel/preset-env": "7.18.0",
"@fortawesome/fontawesome-svg-core": "1.2.36",
"@redux-devtools/extension": "3.2.2",
"@sentry/browser": "5.30.0",
"@sentry/webpack-plugin": "1.17.1",
"@svgr/webpack": "4.3.3",
"@testing-library/jest-dom": "^5.16.5",
"@types/leaflet": "^1.9.0",
"@types/nouislider": "9.0.7",
"@types/react": "^16.14.34",
"@types/react-beautiful-dnd": "^13.1.4",
"@types/react-custom-scroll": "^4.3.2",
"@types/react-datepicker": "^4.8.0",
"@types/react-redux": "7.1.23",
"@types/react-router": "5.1.18",
"@types/react-router-dom": "5.3.3",
"@types/react-select": "3.1.2",
"@typescript-eslint/eslint-plugin": "2.34.0",
"@typescript-eslint/parser": "^2.34.0",
"awesome-typescript-loader": "5.2.1",
"babel-eslint": "10.1.0",
"babel-jest": "24.9.0",
"babel-loader": "8.2.2",
"babel-plugin-named-asset-import": "0.3.8",
"babel-plugin-transform-runtime": "6.23.0",
"babel-preset-react-app": "9.1.2",
"case-sensitive-paths-webpack-plugin": "2.3.0",
"circular-dependency-plugin": "5.2.2",
"clean-webpack-plugin": "4.0.0",
"compression-webpack-plugin": "^10.0.0",
"css-loader": "3.4.2",
"dotenv-expand": "5.1.0",
"dotenv-webpack": "7.1.0",
"error-overlay-webpack-plugin": "0.4.2",
"eslint": "6.8.0",
"eslint-config-airbnb": "18.2.1",
"eslint-config-prettier": "6.15.0",
"eslint-config-react-app": "5.2.1",
"eslint-loader": "3.0.3",
"eslint-plugin-flowtype": "4.6.0",
"eslint-plugin-import": "2.25.4",
"eslint-plugin-jest": "^27.1.3",
"eslint-plugin-jest-dom": "^4.0.2",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-prettier": "3.4.1",
"eslint-plugin-react": "7.29.4",
"eslint-plugin-react-hooks": "2.5.1",
"eslint-webpack-plugin": "^2.6.0",
"file-loader": "4.3.0",
"fork-ts-checker-webpack-plugin": "6.5.0",
"friendly-errors-webpack-plugin": "1.7.0",
"html-webpack-plugin": "5.5.0",
"husky": "4.3.8",
"jest": "^27.0.6",
"jest-environment-jsdom-fourteen": "1.0.1",
"jest-resolve": "25.4.0",
"jest-transformer-svg": "^1.0.2",
"jest-watch-typeahead": "0.4.2",
"lint-staged": "10.5.4",
"mini-css-extract-plugin": "0.9.0",
"optimize-css-assets-webpack-plugin": "5.0.3",
"pnp-webpack-plugin": "1.6.4",
"prettier": "2.6.0",
"prettier-eslint": "9.0.2",
"redux-devtools-extension": "2.13.9",
"regenerator-runtime": "0.13.9",
"resolve-url-loader": "3.1.1",
"sass": "1.49.9",
"sass-loader": "10.2.1",
"sentry-extra-delete-sourcemap-webpack-plugin": "0.0.2",
"style-loader": "0.23.1",
"terser-webpack-plugin": "2.3.5",
"tsconfig-paths-webpack-plugin": "3.5.2",
"typescript": "3.9.10",
"url-loader": "2.3.0",
"webpack": "5.70.0",
"webpack-bundle-analyzer": "4.5.0",
"webpack-cli": "4.10.0",
"webpack-dev-server": "4.7.4",
"webpack-manifest-plugin": "5.0.0",
"webpack-merge": "5.8.0",
"workbox-webpack-plugin": "6.5.1"
},
"scripts": {
"start": "NODE_ENV=development DOT_ENV_FILE=.env.development HOST=0.0.0.0 PORT=3000 webpack serve --config config/webpack.dev.js",
"stage": "NODE_ENV=development DOT_ENV_FILE=.env.stage HOST=0.0.0.0 PORT=3000 webpack serve --config config/webpack.dev.js",
"stage-sus": "docker-compose -f docker-compose.stage.yml build && docker-compose -f docker-compose.stage.yml push",
"build": "NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=production DOT_ENV_FILE=.env.production HOST=0.0.0.0 PORT=3000 webpack --config config/webpack.prod.js",
"test": "react-scripts test --env=jsdom",
"jest": "DEBUG_PRINT_LIMIT=1000000 jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"prod": "docker-compose build && docker-compose push",
"prodnocache": "docker-compose build --no-cache && docker-compose push",
"lint": "eslint --debug src/",
"lint:write": "eslint --debug src/ --fix",
"prettier": "prettier --write \"src/**/*.{json,js,jsx,tsx,sxss}\"",
"stats": "STATS=server npm run build"
},
"lint-staged": {
"*.(js|jsx|tsx)": [
"npm run lint:write",
"git add"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
">0.2%",
"not dead",
"not op_mini all"
]
}
}
请告诉我如何配置配置,以便只有必要的软件包进入程序集。
现在我使用externals选项从程序集中删除typescript:
externals: {
typescript: 'typescript',
}
但看起来像拐杖
1条答案
按热度按时间yyyllmsg1#
我发现在构建项目时,webpack并没有考虑package.json文件中的devDependencies和依赖项。Webpack分析导入。在我的项目中我发现
它告诉webpack在构建中包含Typescript。我删除了这一行,typescript从构建中消失了