webpack 优化

resolve配置
resolve: {
  alias: {
    // 减少依赖包所在文件的查询时间
    react: path.resolve(__dirname, "../../node_modules/react/dist/react.min.js"),
     ...
  },
  // 与alias类似,减少文件查找时间
  modules:['./src/components'],
  // 减少文件查找类别
   extensions: ['.js', '.json']
}
DLL,预打包
// webpack.dll.js 单独预打包,并且生成json文件
// json文件中包含“./node_modules/react/cjs/react.production.min.js”:{ id: 3, ...... }
// 模块id等信息
  entry: {
    library: ["react",  "react-dom"]
  },
  output: {
    filename: "[name]_[hash].dll.js",  // library.dll.js
    path: path.join(process.cwd(), "dll/library"),
    library: '[name]', // window.react == react.js
  },
  plugins: [
    new webpack.DllPlugin({ // 生成对应的json文件
      name: "[name]",
      path: path.join(process.cwd(), "dll/library/[name].json"),
    })
  ]
// webpack.base.js 
// webpack.DllReferencePlugin根据之前打包的json文件进行引用
plugins: [
    new webpack.DllReferencePlugin({
       manifest: path.join(process.cwd(), "/dll/library/library.json")
    }),
]
缓存的使用
  • css cache缓存
      {
        test: /\.js$/,
        use: [
          'babel-loader?cacheDirectory=true', // 二次构建缓存开启提升40%
          'eslint-loader'
        ],
      },
  • plugins 模块缓存
const HardSourceWebpackPlugin = require("hard-source-webpack-plugin");
 [
new HardSourceWebpackPlugin({}) 
]
并发处理
  • js的并发处理loader,webpack之前happy-pack,webpack4自带thread-loader
      {
        test: /.js$/,
        use: [
          'thread-loader'
        ],
      },
  • css的并发处理plugin
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
    new MiniCssExtractPlugin({
      filename: "[name]_[contenthash:8].css",////都提到build目录下的css目录中
      chunkFilename: "[id][contenthash:8].css"
    }),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: require("cssnano"), // css 并发处理器
    }),
splitChunks分包
  optimization: {
    splitChunks: {
      // async:require.ensure()/import.then()引入的库进行分离(默认),
      // initial: 同步引入的库进行分离,
      //  all:所有引入的库进行分离(推荐)
      chunks: 'all',
      minSize: 0, // 抽离的公共包最小的大小,单位字节
    maxSize: 0, // 最大的大小
    minChunks: 1, // 资源使用的次数(在多个页面使用到), 大于1, 最小使用次数
    maxAsyncRequests: 5, // 并发请求的数量
    maxInitialRequests: 3, // 入口文件做代码分割最多能分成3个js文件
    automaticNameDelimiter: '~', // 文件生成时的连接符
    automaticNameMaxLength: 30, // 自动自动命名最大长度
      name: true, //让cacheGroups里设置的名字有效
      cacheGroups: { //当打包同步代码时,上面的参数生效
        verder: {
          name: "verder",
          test: /[\\/]node_modules[\\/]/, //检测引入的库是否在node_modlues目录下的
          priority: -10, //值越大,优先级越高.模块先打包到优先级高的组里
          // filename: 'vendors.js'//把所有的库都打包到一个叫vendors.js的文件里
        },
        commonUtils: {
          name: "commonUtils",
          test: /[\\/]src[\\/]utils[\\/]/,
          priority: -9,
        },
      }
    },
    minimizer: [
      new TerserPlugin({
        parallel: true,
        cache: true,
      })
    ]
  },
缩减包的体积/其它
  • 动态兼容, polyfill-service,针对浏览器ua下发不同的polyfill文件
  • 图片的压缩算法的原理:tinyPng: 将24位png转化为更小索引的8位图片,去除非必要的matadata信息
  • devtool的选择:
    --------------使用————————————————
  • eval 定位webpack后的代码
  • cheap-eval-source-map 进过loader转化后的代码
  • cheap-module-eval-source-map 源代码只能看行
  • eval-source-map 源代码
  • cheap-source-map loader后无列信息源代码
  • cheap-module-source-map 后无列信息源代码
  • source-map 源代码
  • inline-source-map 源代码
  • hidden-source-map 源代码,注释的形式和原文件打包
    sourcemap的主要原理:
{
  version : 3,                          // 版本
  file: "out.js",                       // 转换后文件目录
  sourceRoot : "",                      // 转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空。
  sources: ["foo.js", "bar.js"],        // 转换前的文件。该项是一个数组,表示可能存在多个文件合并
  names: ["src", "maps", "are", "fun"], // 转换前的变量名称
  mappings: "AAgBC,SAAQ,CAAEA"          // 记录位置信息的字符窜
}
- 主要原理在于mapping是如何实现的
- 位置对应原理: 
  五位的字符长度(如上述mapping中: “AAgBC”)
  [“转换后的代码的第几列”,“哪个source文件”,“转换之前第几行”,“转换之后第几列”,“属于names中的哪个变量”]
- 每一位上采用的是VLQ编码
- VLQ编码流程: 
  “16”(变量) --> 
  "10000"(二进制) --> 
  "100000"(>0补0) --> 
  "00001"+"00000"(按5位分割) --> 
  "100000"+"00000"(反转)  --> 
  “gB”(进行base64编码)【得到“16”的最后编码结果】
按需加载

使用import().then()或者require().ensure()
react下的异步组件

import React, { lazy, Suspense } from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}

推荐阅读更多精彩内容

  • 概念: promise接受一个函数 有三种 状态 俩个回调写一个构造函数接收一个参数 有三种状态 成功结果 失...
    A_dfa4阅读 704评论 3 14
  • 开发的时候,用到这么多的第三方包,难免有需要修改他们内部源码的时候,当你修改之后,下次yarn、npm insta...
    朱传武阅读 89评论 0 2
  • 最近在做微信小程序优惠券的一个需求,然后优惠券卡片展示是不规则图形且含阴影。 如下: 因为卡片有展开交互,所以高度...
    越前君阅读 157评论 0 3
  • 大概这样的简单官网,没有考虑ssr,接下来咱们进入正题~正式搭建。 确定你的电脑有木有vue的环境~vue cre...
    涵子_阅读 5,190评论 5 25
  • 自用第一步, 把项目里 upload 文件夹复制到你项目根目录 第二步, 下载该js相关依赖npm 或 cnpm ...
    宇少_e010阅读 2,178评论 0 14