webpack项目优化分享

301 阅读2分钟

webpack 优化相关

1. dll 动态链库配置

// vue.config.js
new webpack.DllReferencePlugin({
   context: __dirname,
   manifest: require('./vendor-manifest.json'),
})

// webpack.dll.config.js
const path = require('path');
const webpack = require('webpack');

module.exports = {
  // 你想要打包的模块的数组
  entry: {
    vendor: ['vue/dist/vue.esm.js', 'vuex', 'axios', 'vue-router'],
  },
  output: {
    path: path.join(__dirname, './public/static/js'), // 打包后文件输出的位置
    filename: '[name].dll.js',
    library: '[name]_library',
    // vendor.dll.js中暴露出的全局变量名。
    // 主要是给DllPlugin中的name使用,
    // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '.', '[name]-manifest.json'),
      name: '[name]_library', // 以上都是不需要改动的库 所以不需要加入hash值
      context: __dirname,
    }),
  ],
};

// index.html
<script src="<%= BASE_URL %>static/js/vendor.dll.js"></script>

2. 模块懒加载

const Home = () => import(/* webpackChunkName: "home" */ './index.vue');

3. 配置别名

    config.resolve.alias
      .set('@store', resolve('src/store'))
      .set('@components', resolve('src/components'))
      .set('@assets', resolve('src/assets'))
      .set('@utils', resolve('src/utils'));

4. 去除 console.log

        new TerserPlugin({
          terserOptions: {
            ecma: undefined,
            warnings: true,
            parse: {},
            compress: {
              drop_console: false,
              drop_debugger: false,
              pure_funcs: ['console.log'],
            },
          },
        }),

5. 添加版本部署信息

// vue.config.js
// 获取部署版本信息
function getGitVersionInfo() {
  try {
    const exec = require("child_process").execSync;

    const branchName = exec("git branch")
      .toString()
      .match(/\*\s+(.+)/)[1];
    const commitHash = exec("git log")
      .toString()
      .match(/^commit\s+(.+)/)[1]
      .slice(0, 8);

    return { branchName, commitHash };
  } catch (e) {
    return { branchName: "unknown", commitHash: "unknown" };
  }
}
// 获取部署时间
function getTimeStamp() {
  const now = new Date();

  const year = now.getFullYear();
  const month =
    now.getMonth() + 1 > 9 ? now.getMonth() + 1 : `0${now.getMonth() + 1}`;
  const date = now.getDate() > 9 ? now.getDate() : `0${now.getDate()}`;

  const hour = now.getHours() > 9 ? now.getHours() : `0${now.getHours()}`;
  const min = now.getMinutes() > 9 ? now.getMinutes() : `0${now.getMinutes()}`;
  const sec = now.getSeconds() > 9 ? now.getSeconds() : `0${now.getSeconds()}`;

  return `${year}-${month}-${date} ${hour}:${min}:${sec}`;
}
// 返回部署信息
function genBuildInfo() {
  let result = "";

  const gitInfo = getGitVersionInfo();
  result = `%c ***: ${gitInfo.branchName} -> ${
    gitInfo.commitHash
  } -> ${getTimeStamp()} `;

  return result;
}

process.env.VUE_APP_BUILD_INFO = genBuildInfo(); // 带时间的部署版本信息(包括git信息)

// main.js
if (process.env.NODE_ENV !== "development") {
  console.warn(
    process.env.VUE_APP_BUILD_INFO,
    "color: #fff; background-color: #fd6720; border-radius: 4px; padding: 2px 0;"
  );
}

6. autoprefixer 自动增加 css3 浏览器前缀

// .postcss.config.js
module.exports = {
  plugins: {
    autoprefixer: {},
  },
};

// package.json
  "browserslist": [
    "> 1%",
    "last 3 versions",
    "not ie <= 8",
    "chrome >= 14",
    "safari >= 3",
    "ios >= 8",
    "android >= 4.0"
  ]

7. 忽略第三方包指定目录 IgnorePlugin

config
      .plugin("ignore")
      // 忽略/moment/locale下的所有文件
      .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));

8. happypack 多线程打包

    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'Happypack/loader?id=js'
            },
            {
                test: /\.css$/,
                use: 'Happypack/loader?id=css'
            }
        ]
    },
    plugins: [
        new Happypack({
            id: 'js',
            use: [
                {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            '@babel/preset-env',
                            '@babel/preset-react'
                        ]
                    }
                }
            ]
        }),
        new Happypack({
            id: 'css',
            use: ['style-loader', 'css-loader']
        })
    ]

9. 热更新

// webpack.config.js文件

// 引入webpack
const webpack = require('webpack');

module.exports = {
    devServer: {
        hot: true,  // 启动热更新
        port: 8080,
        contentBase: './dist'
    },
    plugins: [
        // webpack支持热更新插件
        new webpack.HotModuleReplacementPlugin(),
        // 打印更新了的文件路径
        new webpack.NamedModulesPlugin()
    ]
};


// index.js
// 热更新
// 在src目录下新创建了audio.js文件
// 需要导入这个文件,不然热更新失效
import audio from './audio';

// 检查是否支持热更新
if (module.hot) {
    // 接收热更新的模块
    module.hot.accept('./audio.js', (path) => {
        console.log(path);
        console.log('audio文件更新了');
    });
}

10. splitChunks 代码分割

      splitChunks: {
        chunks: 'async',
        minSize: 10000, // 模块的最小体积
        minChunks: 1, // 模块的最小被引用次数
        maxAsyncRequests: 5, // 按需加载的最大并行请求数
        maxInitialRequests: 3, // 一个入口最大并行请求数
        automaticNameDelimiter: '~', // 文件名的连接符
        name: true,
      },

11. 小图片转成base64格式

{
    test: /\.(png|jpg|jpeg|gif|svg)$/,
    loader: 'url-loader',
    options: {
        limit: 1024,  //小于该值的图片会使用base64编码
        name: '[name].[hash:8].[ext]'  //打包后的图片名称 [ext]指图片格式
    }
}

12. css抽成一个, 并增加contentHash

const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 新增
module.exports = {
  mode: "production",
  entry: {
    index: "./src/index.js",
    chunk1: "./src/chunk1.js"
  },
  output: {
    filename: "[name].[chunkhash].js"
  },
  module: { // 新增
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader, 
          "css-loader"
        ]
      }
    ]
  },
  plugins: [ // 新增
    // 提取css插件
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].[contenthash].css"
    })
  ]
};