reactjs 如何从webpack v5生产版本中删除不必要的库

pw136qt2  于 2023-05-17  发布在  React
关注(0)|答案(1)|浏览(133)

在使用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',
}

但看起来像拐杖

yyyllmsg

yyyllmsg1#

我发现在构建项目时,webpack并没有考虑package.json文件中的devDependencies和依赖项。Webpack分析导入。在我的项目中我发现

import {something} from "typesctipt"

它告诉webpack在构建中包含Typescript。我删除了这一行,typescript从构建中消失了

相关问题