655 webpack的Tree Shaking、Scope Hoisting:usedExports,sideEffects,CSS实现Tree Shaking,PurgeCss

什么是Tree Shaking


webpack实现Tree Shaking


usedExports


sideEffects


Webpack中tree shaking的设置


CSS实现Tree Shaking

  • cnpm install purgecss-webpack-plugin -D


配置PurgeCss


Scope Hoisting


目录结构


main.js

import { sum } from './math';

// 【有副作用的模块不会删除,没有的会删除。有副作用:就是对整个项目代码有影响。】
// 【没有写在sideEffects的数组中的,就是没有副作用,会被删除。】
import "./format";
import("./abc").then(res => {
  
});
import "./style.css";

console.log(sum(20, 30));

console.log(window.abc);

package.json

{
  "name": "webpack_devserver",
  "sideEffects": false,
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config ./config/webpack.common.js --env production",
    "serve": "webpack serve --config ./config/webpack.common.js --env development"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.12.17",
    "@babel/preset-env": "^7.12.17",
    "@babel/preset-react": "^7.12.13",
    "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^5.0.2",
    "css-minimizer-webpack-plugin": "^1.2.0",
    "html-webpack-plugin": "^5.2.0",
    "mini-css-extract-plugin": "^1.3.9",
    "purgecss-webpack-plugin": "^4.0.2",
    "react-refresh": "^0.9.0",
    "style-loader": "^2.0.0",
    "vue-loader": "^15.9.6",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^5.23.0",
    "webpack-cli": "^4.5.0",
    "webpack-dev-server": "^3.11.2",
    "webpack-merge": "^5.7.3"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "dayjs": "^1.10.4",
    "express": "^4.17.1",
    "lodash": "^4.17.21",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-router-dom": "^5.2.0",
    "terser": "^5.6.0",
    "vue": "^2.6.12",
    "webpack-dev-middleware": "^4.1.0"
  }
}

webpack.common.js

const resolveApp = require("./paths");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const TerserPlugin = require("terser-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');

const { merge } = require("webpack-merge");

const prodConfig = require("./webpack.prod");
const devConfig = require("./webpack.dev");

const commonConfig = (isProduction) => {
  return {
    entry: {
      main: "./src/main.js",
      // index: "./src/index.js"
    },
    output: {
      path: resolveApp("./build"),
      filename: "js/[name].[chunkhash:6].bundle.js",
      chunkFilename: "js/[name].[contenthash:6].chunk.js",
      publicPath: ""
    },
    resolve: {
      extensions: [".wasm", ".mjs", ".js", ".json", ".jsx", ".ts", ".vue"],
      alias: {
        "@": resolveApp("./src"),
        pages: resolveApp("./src/pages"),
      },
    },
    optimization: {
      // 对代码进行压缩相关的操作
      // natural: 使用自然数(不推荐),
      // named: 使用包所在目录作为name(在开发环境推荐)
      // deterministic: 生成id, 针对相同文件生成的id是不变
      // chunkIds: "deterministic",
      splitChunks: {
        // async异步导入
        // initial同步导入
        // all 异步/同步导入
        chunks: "all",
        // 最小尺寸: 如果拆分出来一个, 那么拆分出来的这个包的大小最小为minSize
        minSize: 20000,
        // 将大于maxSize的包, 拆分成不小于minSize的包
        maxSize: 20000,
        // minChunks表示引入的包, 至少被导入了几次
        minChunks: 1,
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            filename: "js/[id]_vendors.js",
            // name: "vendor-chunks.js",
            priority: -10
          },
          // bar: {
          //   test: /bar_/,
          //   filename: "[id]_bar.js"
          // }
          default: {
            minChunks: 2,
            filename: "common_[id].js",
            priority: -20
          }
        }
      },
      // true/multiple
      // single
      // object: name
      // runtimeChunk: {
      //   name: function(entrypoint) {
      //     return `why-${entrypoint.name}`
      //   }
      // }
    },
    module: {
      rules: [
        {
          test: /\.jsx?$/i,
          use: "babel-loader",
        },
        {
          test: /\.vue$/i,
          use: "vue-loader",
        },
        {
          test: /\.css/i,
          // style-lodader -> development
          use: [
            isProduction ? MiniCssExtractPlugin.loader : "style-loader",
            "css-loader"
          ],
          // 【有副作用的模块不会删除,没有的会删除。有副作用:就是对整个项目代码有影响】
          // 【没有写在sideEffects的数组中的,就是没有副作用,会被删除。】
          // 只要是匹配到css文件,就是有副作用的,都不删除
          sideEffects: true // react 脚手架中
        },
      ],
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: "./index.html",
      }),
      new VueLoaderPlugin(),
      // 当在代码中遇到某一个变量找不到时, 我们会通过ProvidePlugin, 自动导入对应的库
      // new webpack.ProvidePlugin({
      //   axios: "axios",
      //   get: ["axios", "get"]
      // })
    ],
  };
}

module.exports = function (env) {
  const isProduction = env.production;
  process.env.NODE_ENV = isProduction ? "production" : "development";

  const config = isProduction ? prodConfig : devConfig;
  const mergeConfig = merge(commonConfig(isProduction), config);

  return mergeConfig;
};

webpack.prod.js

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const PurgeCssPlugin = require('purgecss-webpack-plugin');
const webpack = require('webpack');
const glob = require('glob');

const resolveApp = require('./paths');

const isProduction = true;

module.exports = {
  mode: "development",
  devtool: "source-map",
  externals: {
    lodash: "_",
    dayjs: "dayjs"
  },
  optimization: {
    // 【usedExports:做tree shaking,设置为true,要和minimize、Terser配合使用。】
    // usedExports: 目的是标注出来哪些函数是没有被使用 unused 
    usedExports: true, // production模式下默认就是true
    minimize: true,
    minimizer: [
      // 由Terser将未使用的函数, 从我们的代码中删除
      new TerserPlugin({
        parallel: true,
        extractComments: false,
        terserOptions: {
          compress: {
            arguments: false,
            dead_code: true
          },
          mangle: true,
          toplevel: true,
          keep_classnames: true,
          keep_fnames: true
        }
      })
    ]
  },
  plugins: [
    // 生成环境
    new CleanWebpackPlugin({}),
    new MiniCssExtractPlugin({
      filename: "css/[name].[contenthash:6].css"
    }),
    new CssMinimizerPlugin(),
    // 【Scope Hoisting:对作用域进行提升】
    new webpack.optimize.ModuleConcatenationPlugin(),
    // purge: 清除
    new PurgeCssPlugin({
      // 写绝对路径,所有文件夹里的所有文件,不是文件夹,注意是paths,有s
      paths: glob.sync(`${resolveApp("./src")}/**/*`, {nodir: true}),
      // 白名单
      safelist: function() {
        return {
          standard: ["body", "html"]
        }
      }
    })
  ]
}

webpack.dev.js

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const PurgeCssPlugin = require('purgecss-webpack-plugin');
const webpack = require('webpack');
const glob = require('glob');

const resolveApp = require('./paths');

const isProduction = true;

module.exports = {
  mode: "development",
  devtool: "source-map",
  externals: {
    lodash: "_",
    dayjs: "dayjs"
  },
  optimization: {
    // 【usedExports:做tree shaking,设置为true,要和minimize、Terser配合使用。】
    // usedExports: 目的是标注出来哪些函数是没有被使用 unused 
    usedExports: true, // production模式下默认就是true
    minimize: true,
    minimizer: [
      // 由Terser将未使用的函数, 从我们的代码中删除
      new TerserPlugin({
        parallel: true,
        extractComments: false,
        terserOptions: {
          compress: {
            arguments: false,
            dead_code: true
          },
          mangle: true,
          toplevel: true,
          keep_classnames: true,
          keep_fnames: true
        }
      })
    ]
  },
  plugins: [
    // 生成环境
    new CleanWebpackPlugin({}),
    new MiniCssExtractPlugin({
      filename: "css/[name].[contenthash:6].css"
    }),
    new CssMinimizerPlugin(),
    // 【Scope Hoisting:对作用域进行提升】
    new webpack.optimize.ModuleConcatenationPlugin(),
    // purge: 清除
    new PurgeCssPlugin({
      // 写绝对路径,所有文件夹里的所有文件,不是文件夹,注意是paths,有s
      paths: glob.sync(`${resolveApp("./src")}/**/*`, {nodir: true}),
      // 白名单
      safelist: function() {
        return {
          standard: ["body", "html"]
        }
      }
    })
  ]
}

posted on 2021-03-17 20:35  冲啊!  阅读(328)  评论(0编辑  收藏  举报

导航