美文网首页
webpack性能优化及性能分析

webpack性能优化及性能分析

作者: 巧克力_404 | 来源:发表于2021-03-31 18:08 被阅读0次

webpack对我们来说即熟悉又陌生,说他熟悉是因为几乎现在所有的项目中都用到了他,说他陌生是因为对于webpack繁多的配置项又不是很清楚,今天我们就来一起缕一下webpack中的配置项都是做什么,如何有针对性的做到性能优化,提升开发体验。
首先上一盘儿基本配置

const path = require("path");
const miniCssExtractPlugin = require("mini-css-extract-plugin");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");
module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "[name]-[hash:6].js",
  },
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css$/,
        include: path.resolve(__dirname, "./src"),
        use: ["style-loader", "css-loader"],
      },
    ],
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src/style"),
    },
    modules: [path.resolve(__dirname, "./node_modules")],
    extensions: [".js", ".json", ".jsx", ".vue"], //后缀列表 希望大家不要省略后缀,因为会浪费查询时间。
  },
  devServer: {
    contentBase: "./dist",
    open: true,
    port: 8081,
    proxy: {
      "/api": {
        target: "http://localhost:9092/",
      },
    },
    hot: true,
    hotOnly: true,
  },
  devtool: "inline-source-map", //更容易追踪到错误的信息
  plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html",
      filename: "index.html",
    }),
    new CleanWebpackPlugin(), //清理目录
    new webpack.HotModuleReplacementPlugin(), //启用热更新模块
  ],
};

入口文件是entry: "./src/index.js", 出口文件是在dist目录,bundle文件是用的hash模式;
mode模式是用的开发development;
module的rules里让webpack支持了css模块,less模块还有图片和第三方字体模块,js模块通过babel来实现语意转化;

//...
rules: [
      {
        test: /\.css$/,
        include: path.resolve(__dirname, "./src"),
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        include: path.resolve(__dirname, "./src"),
        use: [
          // miniCssExtractPlugin.loader,
          "style-loader",
          "css-loader",
          "postcss-loader",
          "less-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        include: path.resolve(__dirname, "./src"),
        use: {
          loader: "url-loader",
          options: {
            name: "[name].[ext]",
            outputPath: "images/",
            limit: 2048,
          },
        },
      },
      {
        test: /\.woff2$/,
        include: path.resolve(__dirname, "./src"),
        use: "file-loader",
      },
      {
        test: /\.js$/,
        include: path.resolve(__dirname, "./src"),
        use: "babel-loader",
      },
    ],
//...

devServer来实现本地服务器的一个功能;
devtool: surceMap功能,可以将编译后的代码映射到原始的代码位置;
plugins里使用的htmlWebpackPlugin,可以配置生成html文件的标题

//...
new htmlWebpackPlugin({
      template: "./src/index.html",
      filename: "index.html",
      inject: ""//true body head false,
      favicon: 'path/to/my_favicon.ico',
      minify: {
            removeAttributeQuotes: true // 移除属性的引号
        },
     cache:true //默认是true的,表示内容变化的时候生成一个新的文件
     showErrors: true //当webpack报错的时候,会把错误信息包裹再一个pre中,默认是true
     chunks: ["main"],
     excludeChunks: ['devor.js'] , //排除掉一些js 
    }),
///...

① template指定你生成的文件所依赖哪一个html文件模板,模板类型可以是html、jade、ejs等
② inject的值true body head false

  • true 默认值,script标签位于html文件的 body 底部;
  • body script标签位于html文件的 body 底部;
  • head script标签位于html文件的 head中;
  • false 不插入生成的js文件,这个几乎不会用到的;
    ③ favicon 显而易见是为我们生产的html配置favicon ,值是一个路径
    ④ minify 使用minify会对生成的html文件进行压缩,默认值是false
    ⑤ chunks 主要用于多入口文件,当你有多个入口文件,编译后生成多个打包后的文件,那么chunks 就能选择你要使用那些js文件
    ⑥⑦⑧⑨⑩
    随着我们的项目越来越多,集成的插件和loader越来越多,打包的时间是越来越久了,所以webpack性能优化,主要分两点:
    1 优化开发体验
    2 优化输出质量
    优化开发体验,我们可以对配置文件,做一个功能上的拆分:
    我们按功能划分webpack.base.config/webpack.dev.config/webpack.prod.config,从名字上可以猜出来是做什么用的,接下来我们看下那些功能是需要放在基础的功能配置里面呢
//webpack.base.config.js
  entry: "./src/index.js",
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/,
        include: path.resolve(__dirname, "./src"),
        use: {
          loader: "url-loader",
          options: {
            name: "[name].[ext]",
            outputPath: "images/",
            limit: 2048,
          },
        },
      }
    ],
  },
  plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html",
      filename: "index.html",
      chunks: ["main"],
    }),
    new CleanWebpackPlugin(),
  ]
//webpack.dev.config.js
//...
output: {
    path: path.resolve(__dirname, "./dev"),
    filename: "[name]-[hash:6].js",
  },
  mode: "development",
  module: {
    rules: [
      {
        test: /\.less$/,
        include: path.resolve(__dirname, "./src"),
        use: ["style-loader", "css-loader", "postcss-loader", "less-loader"],
      },
    ],
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src/style"),
    },
    modules: [path.resolve(__dirname, "./node_modules")],
    extensions: [".js", ".json", ".jsx", ".vue"], //后缀列表 希望大家不要省略后缀,因为会浪费查询时间。
  },
  devServer: {
    contentBase: "./dist",
    open: true,
    port: 8081,
    proxy: {
      "/api": {
        target: "http://localhost:9092/",
      },
    },
    hot: true,
    hotOnly: true,
  },
  devtool: "inline-source-map",
  plugins: [new webpack.HotModuleReplacementPlugin()],
//...
//..webpack.prod.config
output: {
    path: path.resolve(__dirname, "./build"),
    filename: "[name]-[hash:6].js",
  },
  mode: "production",
  module: {
    rules: [
      {
        test: /\.less$/,
        include: path.resolve(__dirname, "./src"),
        use: [
          miniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "less-loader",
        ],
      },
    ],
  },
  optimization: {
    usedExports: true,
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src/style"),
    },
    modules: [path.resolve(__dirname, "./node_modules")],
    extensions: [".js", ".json", ".jsx", ".vue"], //后缀列表 希望大家不要省略后缀,因为会浪费查询时间。
  },
  plugins: [
    new miniCssExtractPlugin({
      filename: "css/index-[contenthash:6].css",
    }),
    new purifycss({
      paths: glob.sync([
        path.resolve(__dirname, "./src/*.html"),
        path.resolve(__dirname, "./src/*.js"),
      ]),
    }),
    new optimizeCss({
      cssProcessor: require("cssnano"),
    }),
  ],
//..

按功能拆分之后,看一下怎么合并呢?

npm install webpack-merge -D

给各个环境的配置起一个名字 const prodConfig,在dev中导入base配置,和安装的merge插件,使用module.exports合并导出

const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base.config.js");
//..
module.exports = merge(baseConfig, devConfig);

接下来我们怎么使用呢

//package.json
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "mpa": "cross-env NODE_ENV=Davy webpack --config ./webpack.mpa.config.js --env.development",
    "server": "webpack-dev-server ",
    "dev-new": "webpack --config ./webpack.dev.config.js",
    "build-new": "webpack --config ./webpack.prod.config.js"
  },
在这里我们解释一下,croess-env跨平台写入环境变量,通过注入变量的方式,往往我们都需要借助croess-env来解决这种各平台的兼容问题,可以跟据NODE_ENV=Davy变量来写判断了,从而可以达到跟据一个配置还对不同的环境输出,那么这个变量我们是如何获得的呢,可以看到我们将脚本命令写在mpa下了,在webpack.mpa.config.js文件中中通过 console.log(process.env.NODE_ENV)传进来的变量 process.env.NODE_ENV.png
说完merge合并,下面看一下代码压缩

css压缩
post-css 生态非常强大,有各种css插件,有压缩的,有处理Css的,它本身不做任何压缩处理
代码压缩
去掉冗余样式 tree shaking,可以检查没有用的Css 或js 在打包的时候 去除掉

npm i glob-all purify-css pruifycss-webpack  
//..
new purifycss({
      paths: glob.sync([
        path.resolve(__dirname, "./src/*.html"), //选择摇src目录下的html文件
        path.resolve(__dirname, "./src/*.js"),
      ]),
    }),
//..

压缩js

optimization: {
    usedExports: true, //开启js tree shaking
  }
//开启了之后,在打包的js文件中,我们可以看到 /*! exports provided: default */
//注意在开发模式下是没有效果的,但是通过这个注释我们可以看到生效了
网站性能优化的分析工具

读懂核心指标
chrome lighthouse(灯塔)

npm install -g lighthouse
//谷歌判断网站性能优化的核心指标

webpack中文文档 : https://webpack.html.cn/plugins/hot-module-replacement-plugin.html

相关文章

网友评论

      本文标题:webpack性能优化及性能分析

      本文链接:https://www.haomeiwen.com/subject/jihdhltx.html