面试题:webpack之性能优化

移除插件某些包,减小插件体积

好比说通用的日期库是moment.js,这个库会占用很大的体积,由于当引用这个库的时候,全部的locale文件都被引入,而这些文件甚至在整个库的体积中占了大部分, 要想对此进行优化必须在webpack打包时移除这部份内容

webpack自带的IgnorePlugin插件便会处理进行优化
javascript

plugins:[    
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]复制代码

以上配置忽略了时间格式化moment.js中的语言包
java

优化前node


优化后react



模块化引入 按需导出

咱们在引入lodash这种重型的js库的时候,咱们可能只须要引用里面部分函数,可是当咱们所有引入打包lodash.js体积就会很庞大webpack

优化前es6


import _ from 'lodash';

console.log(_.map)
//ƒ map(collection,iteratee){var func=isArray(collection)?arrayMap:baseMap;return func(collection,getIteratee(iteratee,3));}复制代码

可是咱们若是按需导入 这样就会减小很大致积web

优化后json


import map from 'lodash/map';

console.log(map)
//ƒ map(collection, iteratee) {
  var func = isArray(collection) ? arrayMap : baseMap;
  return func(collection, baseIteratee(iteratee, 3));
}复制代码


优化resolve.extensions配置 设置解析文件后缀

设置解析文件后缀,能够加速文件寻找速度
resolve: {
    extensions: ['.js', '.json', 'jsx']
}复制代码


优化resolve.modules配置

 resolve.modules 用于配置Webpack去哪些目录下寻找第三方模块。resolve.modules的默认值是[node modules],含义是先去当前目录的/node modules目录下去找咱们想找的模块,若是没找到,就去上一级目录../node modules中找,再没有就去../ .. /node modules中找,以此类推,这和Node.js的模块寻找机制很类似。当安装的第三方模块都放在项目根目录的./node modules目录下时,就没有必要按照默认的方式去一层层地寻找,能够指明存放第三方模块的绝对路径,以减小寻找。  
resolve: {
    // 使用绝对路径指明第三方模块存放的位置,以减小搜索步骤
    modules: [path.resolve(__dirname,'node_modules')]
}复制代码

优化loader配置 缩小文件搜索范围

因为Loader对文件的转换操做很耗时,因此须要让尽量少的文件被Loader处理。咱们能够经过如下3方面优化Loader配置: 
(1)优化正则匹配 
(2)经过cacheDirectory选项开启缓存 
(3)经过include、exclude来减小被处理的文件。 
module: {
    rules: [
        {
            test:/\.js$/,
            //babel-loader支持缓存转换出的结果,经过cacheDirectory选项开启
            loader:'babel-loader?cacheDirectory',
            //只对项目根目录下的src 目录中的文件采用 babel-loader
            include: [path.resolve('src')],
            //排除 node_modules 目录下的文件,node_modules 目录下的文件都是采用的 ES5 语法,不必再经过 Babel 去转换
            exclude: path.resolve(__dirname, 'node_modules')
        }
    ]
}复制代码

optimization.splitChunks 提取公共代码

Webpack 4 移除了 CommonsChunkPlugin取而代之的是两个新的配置项 optimization.splitChunks 和 optimization.runtimeChunk。
redux

CommonsChunkPlugin
缓存

webpack 将多个模块打包以后的代码集合称为 chunk。为了将一些不多变化的经常使用库(react、redux、lodash)与业务代码分开,或者是一些不一样入口共同使用的公共模块,开发者经常须要将它们单独打包,这些均可以经过配置 CommonsChunkPlugin 来实现。

entry: {
    app:'./main.js',
    vendor: ['react','react-dom']
},
plugins:
    new webpack.optimize.CommonsChunkPlugin({names:['vendor']})
]

复制代码

webpack 4 准备经过 optimization.splitChunks 和 optimization.runtimeChunk 属性来简化代码分割的配置

optimization.splitChunks

经过设置 optimization.splitChunks.chunks: "all" 来启动默认的代码分割配置项。  

当知足以下条件时,webpack 会自动打包 chunks: 

1)当前模块是公共模块(多处引用)或者模块来自 node_modules 

2)当前模块大小大于 30kb 若是此模块是按需加载,并行请求的最大数量小于等于 5 

3)若是此模块在初始页面加载,并行请求的最大数量小于等于 3

optimization: {
    splitChunks: {
        chunks: 'all',
        name: true,
        automaticNameDelimiter: '-',  // 模块间的链接符,默认为"~"
        cacheGroups: {
            vendors: {
                test: /[\\/]node_modules[\\/]/,
                priority: -10  // 优先级,越小优先级越高
            },
            default: {  // 默认设置,可被重写
                minChunks: 2,
                priority: -20,
                reuseExistingChunk: true  // 若是原本已经把代码提取出来,则重用存在的而不是从新产生
            }
        }
    }
}复制代码


用 Happypack 来加速代码构建

因为有大量文件须要解析和处理,构建是文件读写和计算密集型的操做,特别是当文件数量变多后,Webpack 构建慢的问题会显得严重。 
运行在 Node.js 之上的 Webpack 是单线程模型的,也就是说 Webpack 须要处理的任务须要一件件挨着作,不能多个事情一块儿作。 文件读写和计算操做是没法避免的,那能不能让 Webpack 同一时刻处理多个任务,HappyPack 就能让 Webpack 作到这点,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
当同时读取多个loader文件资源时,好比`babel-loader`须要 transform 各类jsx,es6的资源文件。在这种同步计算同时须要大量耗费 cpu 运算的过程当中,node的单进程模型就无优点了,而 Happypack 就是针对解决此类问题而生的存在
const HappyPack = require('happypack');
module: {    rules: [
        {
            test:/\.js/,
            //loader:'babel-loader',
            include: [path.resolve('src')],
            // 排除 node_modules 目录下的文件,node_modules 目录下的文件都是采用的 ES5 语法,不必再经过 Babel 去转换
            exclude: path.resolve(__dirname, 'node_modules'),
            // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例
            loader: 'happypack/loader?id=babel'
        }
    ]
},
plugins:[    new HappyPack({
        // 用惟一的标识符 id 来表明当前的 HappyPack 是用来处理一类特定的文件
        id: 'babel',
        // 如何处理 .js 文件,用法和 Loader 配置中同样
        loaders: ['babel-loader?cacheDirectory'],
        // ... 其它配置项
    })
]

复制代码

未完待续................

相关文章
相关标签/搜索