精华内容
下载资源
问答
  • webpack - 打包速度优化

    千次阅读 2018-08-01 14:38:59
    DllPlugin DllReferencePlugin 这两个插件设置打包好的第三方代码不再打包 第一步: 在build文件中新建一个webpack.dll.config.js 第二部: 配置webpack.dll.config.js const path = require('path'); cons....

    方法一:
    区分第三方代码(vender)和业务代码(app)
    DllPlugin DllReferencePlugin 这两个插件设置打包好的第三方代码不再打包
    第一步: 在build文件中新建一个webpack.dll.config.js
    第二部: 配置webpack.dll.config.js

     const path = require('path');
     const webpack = require('webpakc')
     module.exports = {
      entry:{
        vue:['vue','vue-router'],
        ui:['element-ui']
      },
      output:{
        path:path.join(__dirname,'../src/dll/'), //新建一个目录,存放dll文件
        filename:'[name].dll.js',
        library:'[name]', // 怎么引用打包好的第三方库
      },
      plugins:[
        new webpack.DllPlugin({
          path: path.join(__dirname,'../src/dll/','[name]-manifest.json'), // 打包后的dll文件放在位置及名称
          name:'[name]'
        }),
        // 混淆压缩
        new webpack.optimize.UglifyJsPlugin()
    
      ]
    }

    第三步: 命令行打包: webpack –config build/webpack.dll.config.js
    第四部: 在webpack.prod.conf.js中加入如下代码:

    plugin:[
        new webpack.DllReferencePlugin({
            manifest: require('../src/dll/ui-manifest.json')
        }),
        new webpack.DllReferencePlugin({
            manifest: require('../src/dll/vue-manifest.json')
        })
        ....
    ]

    方法二: 并行进行代码压缩混淆
    插件: UglifyJsPlugin 压缩混淆代码
    设置:paraller cache

    // 修改webpack.prod.conf.js
    plugins:[
        new UglifyJsPlugin({
                uglifyOptions:{
                    compress:{
                    warnings: false,
                    }
                },
                sourceMap: false,
                parallel: true , // 并行处理打包文件
                cache: true, // 使用缓存
        })
    ]

    方法三:
    happyPack 将串行变为并行
    happyPack.TheadPool 线程池
    安装 : npm install happypack –save-dev

    // 修改webpack.prod.conf
    const HappyPack = require('happypack')
    
     plugins:[
      new HappyPack({
        id:'vue',
        loaders:[
          {
            loader:'vue-loader',
            option:require('./vue-loader.conf')
          }
        ]
      })
    //修改webpack.base.conf.js
    {
        test: /\.vue$/,
        loader: 'happypack/loader?id=vue',
        options: vueLoaderConfig
      },

    四: babel-loader
    开启缓存: options.cacheDirectory
    include/exclude: 规定打包的范围

    //修改webpack.base.conf.js
    {
            test: /\.js$/,
            loader: 'babel-loader',
            include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
    
    },
    // 修改include   减少babel-loader的处理范围
    include: [resolve('src')]
    
     //resolve('test'), 开发环境使用
     //resolve('node_modules/webpack-dev-server/client') 开发环境使用
    

    其他因素:
    减少resolve
    DevTool:去除sourcemap
    cache-loader, // 将loader处理结果缓存下来
    升级node,
    升级webpack,

    展开全文
  • webpack4打包优化

    2020-08-07 14:52:13
    title: webpack4打包优化 categories: webpack tags: webpack4打包优化 针对vue cli3.0+,webpack4.0+,nodejs10.0+ 这几个版本打包优化 一、量化、分析 speed-measure-webpack-plugin 时间分析 测量出在你的构建...

    layout: post
    title: webpack4打包优化
    categories: webpack
    tags:

    webpack4打包优化

    针对vue cli3.0+,webpack4.0+,nodejs10.0+ 这几个版本打包优化

    一、量化、分析

    speed-measure-webpack-plugin 时间分析

    • 测量出在你的构建过程中,每一个 Loader 和 Plugin 的执行时长
    • 而它的使用方法也同样简单,如下方示例代码所示,只需要在你导出 Webpack 配置时,为你的原始配置包一层 smp.wrap 就可以了,接下来执行构建,你就能在 console 面板看到如它 demo 所示的各类型的模块的执行时长

    demo

    在这里插入图片描述

    安装

    npm i speed-measure-webpack-plugin -D
    

    使用

    vue.config.js中配置

    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
    const smp = new SpeedMeasurePlugin({
      outputFormat: 'human'
    })
    module.exports = {
      configureWebpack: smp.wrap({
        plugins: []
      })
    }
    

    webpack-bundle-analyzer 体积分析

    • 分析打包后,各个文件的大小,用于分析 bundle 的
      在这里插入图片描述

    安装

    npm i webpack-bundle-analyzer -D
    

    使用

    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    module.exports = {
    configureWebpack: {
       plugins: [
          new BundleAnalyzerPlugin({
            //  可以是`server`,`static`或`disabled`。
            //  在`server`模式下,分析器将启动HTTP服务器来显示软件包报告。
            //  在“静态”模式下,会生成带有报告的单个HTML文件。
            //  在`disabled`模式下,你可以使用这个插件来将`generateStatsFile`设置为`true`来生成Webpack Stats JSON文件。
            analyzerMode: 'server',
            //  将在“服务器”模式下使用的主机启动HTTP服务器。
            analyzerHost: '127.0.0.1',
            //  将在“服务器”模式下使用的端口启动HTTP服务器。
            analyzerPort: 8888, 
            //  路径捆绑,将在`static`模式下生成的报告文件。
            //  相对于捆绑输出目录。
            reportFilename: 'report.html',
            //  模块大小默认显示在报告中。
            //  应该是`stat`,`parsed`或者`gzip`中的一个。
            //  有关更多信息,请参见“定义”一节。
            defaultSizes: 'parsed',
            //  在默认浏览器中自动打开报告
            openAnalyzer: true,
            //  如果为true,则Webpack Stats JSON文件将在bundle输出目录中生成
            generateStatsFile: false, 
            //  如果`generateStatsFile`为`true`,将会生成Webpack Stats JSON文件的名字。
            //  相对于捆绑输出目录。
            statsFilename: 'stats.json',
            //  stats.toJson()方法的选项。
            //  例如,您可以使用`source:false`选项排除统计文件中模块的来源。
            //  在这里查看更多选项:https:  //github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
            statsOptions: null,
            logLevel: 'info' // 日志级别。可以是'信息','警告','错误'或'沉默'。
          })
        ]
      },
    }
    

    二、缓存

    webpack缓存的插件有两个

    • DllPlugin 配置比较繁琐
    • hard-source-webpack-plugin

    DllPlugin

    提取固定三方库预编译,减少打包体积,加快编译速度

    使用

    • 在项目根目录下新建 webpack.dll.conf.js,输入以下内容
    const path = require('path')
    const webpack = require('webpack')
    const CleanWebpackPlugin = require('clean-webpack-plugin')
    
    // dll文件存放的目录
    const dllPath = 'public/vendor'
    
    module.exports = {
      entry: {
        // 需要提取的库文件
        vendor: [
          'vue-router/dist/vue-router.esm.js',
          'vuex/dist/vuex.esm.js',
          'axios',
          'mint-ui',
          'echarts',
          'toastr',
          'mockjs',
          'es6-promise'
        ]
      },
      output: {
        path: path.join(__dirname, dllPath),
        filename: '[name].dll.js',
        // vendor.dll.js中暴露出的全局变量名
        // 保持与 webpack.DllPlugin 中名称一致
        library: '[name]_[hash]'
      },
      plugins: [
        // 清除之前的dll文件
        new CleanWebpackPlugin(['*.*'], {
          root: path.join(__dirname, dllPath)
        }),
        // 设置环境变量
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: 'production'
          }
        }),
        // manifest.json 描述动态链接库包含了哪些内容
        new webpack.DllPlugin({
          path: path.join(__dirname, dllPath, '[name]-manifest.json'),
          // 保持与 output.library 中名称一致
          name: '[name]_[hash]',
          context: process.cwd()
        })
      ]
    }
    
    • 在 package.json 中加入如下命令,生成dll
    "scripts": {
        ...
        "dll": "webpack -p --progress --config ./webpack.dll.conf.js"
    }
    

    配置完成以后运行命令

    npm run dll
    

    在这里插入图片描述

    • 为了节约编译的时间,这时间我们需要告诉 webpack 公共库文件已经编译好了,减少 webpack 对公共库的编译时间。在项目根目录下找到 vue.config.js,配置如下
    const webpack = require('webpack')
    
    module.exports = {
        configureWebpack: {
            plugins: [
              new webpack.DllReferencePlugin({
                context: process.cwd(),
                manifest: require('./public/vendor/vendor-manifest.json')
              })
            ]
        }
    }
    
    
    • 经过上面的配置,公共库提取出来了,编译速度快了,但需要在index.html引用生成的 dll 文件
    <script src="./vendor/vendor.dll.js"></script>
    
    • 不想手动引入也可以 vue.config.js 在 configureWebpack plugins 节点下,配置 add-asset-html-webpack-plugin
    const path = require('path')
    const webpack = require('webpack')
    const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
    
    module.exports = {
        ...
        configureWebpack: {
            plugins: [
              new webpack.DllReferencePlugin({
                context: process.cwd(),
                manifest: require('./public/vendor/vendor-manifest.json')
              }),
              // 将 dll 注入到 生成的 html 模板中
              new AddAssetHtmlPlugin({
                // dll文件位置
                filepath: path.resolve(__dirname, './public/vendor/*.js'),
                // dll 引用路径
                publicPath: './vendor',
                // dll最终输出的目录
                outputPath: './vendor'
              })
            ]
        }
    }
    
    

    打包速度

    • 打包前
      在这里插入图片描述

    • 打包后
      在这里插入图片描述

    包大小(最大的包echarts被移出并预编译)

    • 打包前

    在这里插入图片描述

    • 打包后
      在这里插入图片描述

    • 打包前
      在这里插入图片描述

    • 打包后
      在这里插入图片描述

    hard-source-webpack-plugin

    HardSourceWebpackPlugin 为模块提供中间缓存步骤。为了查看结果,您需要使用此插件运行webpack两次:第一次构建将花费正常的时间。第二次构建将显着加快(大概提升90%的构建速度)

    npm i webpack-bundle-analyzer -D
    
    const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
    module.exports = {
      configureWebpack: smp.wrap({
        plugins: [
          // 为模块提供中间缓存,缓存路径是:node_modules/.cache/hard-source
          new HardSourceWebpackPlugin(),
        ]
      })
    }
    

    tips: webpack5.0会把hard-source-webpack-plugin内置成一个配置。

    三、多进程多实例构建,资源并行解析

    • webpack需要处理的文件是非常多的,构建过程是一个涉及大量文件读写的过程。项目复杂起来了,文件数量变多之后,webpack构建就会特别满,而且运行在nodeJS上的webpack是单线程模型的,也就是说Webpack一个时刻只能处理一个任务,不能同时处理多个任务。

    • 文件读写和计算操作是无法避免的,那能不能让Webpack在同一时刻处理多个任务发挥多核CPU电脑的功能,以提升构建速度呢

    多进程构建的方案比较知名的有以下三个

    • thread-loader (推荐使用这个)
    • HappyPack
    • parallel-webpack

    thread-loader

    webpack4 官方提供了一个thread loader

    把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker【worker pool】 池里运行,一个worker 就是一个nodeJS 进程【node.js proces】,每个单独进程处理时间上限为600ms,各个进程的数据交换也会限制在这个时间内。

    配置长这样:

    npm i thread-loader -D
    
    module.exports = {
      configureWebpack: smp.wrap({
        module: {
          rules: [
            {
              test: /\.js$/,
              include: path.resolve("src"),
              use: [{
                loader: "thread-loader",
                // loaders with equal options will share worker pools
                // 设置同样option的loaders会共享
                options: {
                  // worker的数量,默认是cpu核心数
                  workers: 2,
    
                  // 一个worker并行的job数量,默认为20
                  workerParallelJobs: 50,
    
                  // 添加额外的node js 参数
                  workerNodeArgs: ['--max-old-space-size=1024'],
    
                  // 允许重新生成一个dead work pool
                  // 这个过程会降低整体编译速度
                  // 开发环境应该设置为false
    
                  poolRespawn: false,
    
                  //空闲多少秒后,干掉work 进程
                  // 默认是500ms
                  // 当处于监听模式下,可以设置为无限大,让worker一直存在
                  poolTimeout: 2000,
    
                  // pool 分配给workder的job数量
                  // 默认是200
                  // 设置的越低效率会更低,但是job分布会更均匀
                  poolParallelJobs: 50,
    
                  // name of the pool
                  // can be used to create different pools with elsewise identical options
                  // pool 的名字
                  //
                  name: "my-pool"
                }
              },
              // your expensive loader (e.g babel-loader)
            ]}
          ]
        }
      })
    }
    

    经过测试,thread-loader 对于打包速度几乎没有影响,是因为它本身的额外开销导致,建议只在极高性能消耗的场景下使用

    HappyPack

    将任务分解给多个子进程去并发执行,子进程处理完后再将结果发给主进程

    安装

    npm i happypack -D
    

    使用

    const HappyPack = require('happypack');
    const os = require('os');
    const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
    
    module.exports = {
      configureWebpack: smp.wrap({
        plugins: [
          new HappyPack({
            id: 'babel',
            loaders: ['babel-loader?cacheDirectory=true'],
            threadPool: happyThreadPool
          })
        ]
      }),
      chainWebpack: config => {
    		const jsRule = config.module.rule('js');
        jsRule.uses.clear();
        jsRule.use('happypack/loader?id=babel')
          .loader('happypack/loader?id=babel')
          .end();
    	}
    }
    
    

    经过测试,在我们的项目中,对 js 和 ts 文件使用 happypack 收益最大
    需要注意的是,Vue-loader 不支持 happypack

    四、多进程多实例并行压缩

    • 使用 parallel-uglify-plugin 插件
    • uglifyjs-webpack-plugin 开启 parallel 参数
    • terser-webpack-plugin 开启 parallel 参数 (推荐使用这个,支持 ES6 语法压缩)

    uglifyjs-webpack-plugin

    通过开启 cache 配置开启我们的缓存功能,也可以通过开启 parallel 开启多核编译功能

    安装

    npm i terser-webpack-plugin -D
    

    使用

    const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    
    module.exports = {
      configureWebpack: smp.wrap({
        optimization: {
          minimizer: [
            new UglifyJsPlugin({
              uglifyOptions: {
                warnings: false,
                parse: {},
                // 删除console debugger 删除警告
                compress: {
                  warnings: false,
                  drop_console: true,//console
                  drop_debugger: false,
                  pure_funcs: ['console.log']//移除console
                },
                mangle: true,
                // 删除注释
                output:{
                  comments:false
                },
                toplevel: false,
                nameCache: null,
                ie8: false,
                keep_fnames: false
              },
              cache: true,
              parallel: true
            })
          ]
        }
      })
    }
    

    五、其他

    另外还有一些关于css打包体积的优化

    抽离css

    安装

    npm install --save-dev mini-css-extract-plugin
    

    使用

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    module.exports = {
      plugins: [
        new MiniCssExtractPlugin({
          filename: 'css/[name].[contenthash:8].css'  // 将css文件统一放入css文件夹
        })
      ]  
    }
    

    压缩css

    安装

    npm install -D optimize-css-assets-webpack-plugin
    

    使用

    const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
    
    module.exports = {
      optimization: {
        minimize: true,
        minimizer: [
            new OptimizeCssAssetsWebpackPlugin()
        ]
      }
    }
    
    • 抽离css和压缩css后打包的速度

    在这里插入图片描述

    移除未使用的css

    • 在大型项目中,经常会有很多样式内容,在代码中根本未使用,但是会被打包,这些样式需要打包时应该移除

    安装

    npm i purgecss-webpack-plugin -D
    

    使用

    const PurgecssWebpackPlugin = require('purgecss-webpack-plugin');
    const glob = require('glob'); // 根据路径查找文件
    module.exports = {
      plugins:[
        new PurgecssWebpackPlugin({ //paths要求是绝对路径
          paths: glob.sync(`${path.join(__dirname, 'src/**/*')}`, { nodir: true })
        })
      ]
    }
    
    展开全文
  • 4.webpack4打包简单优化

    2020-09-15 10:47:29
    萌新自己学习webpack做的简单配置,如有错误请多包含,也可指点,谢谢. # noParse 内置 # 设置不去解析的包以提高性能 # IgnorePlugin 内置 # 设置不去打包对应插件内的某些文件 # DllPlugin DllReferencePlugin 内置...

    萌新自己学习webpack做的简单配置,如有错误请多包含,也可指点,谢谢.

    # noParse 内置
    # 设置不去解析的包以提高性能
    
    # IgnorePlugin 内置
    # 设置不去打包对应插件内的某些文件
    
    # DllPlugin DllReferencePlugin 内置
    # 使用额外的配置文件在dist中生成想要换存成dll文件的包
    # 使用DllReferencePlugin读取dist中是否有对应的dll文件,如果有,则不再打包对应的包
    # 需在html中引用dll包对应的js,不然无法找到
    
    # happypack 
    # 如果有比较大的打包需求,可以使用多线程打包提高打包速度
    
    # webpack自带的优化
    # 都是只在生产环境生效的功能
    # tree-shaking  打包时把没用到的代码自动删除掉 只支持 import 导入的模块
    # scope hosting 打包时会自动省略一些可以简化的代码
    

    webpack.config.react.js
    使用webpack执行当前配置文件打包生成react的dll文件,在使用webpack.config.js打包时会去查找是否有对应的dll文件.如果有,则不回去打包对应包

    const path = require('path')
    const webpack = require('webpack')
    module.exports = {
      mode: 'development',
      entry: ['react','react-dom'],
      output: {
        filename: '_dll_[name].js',
        path: path.resolve(__dirname, 'dist'),
        library: '_dll_[name]',  // 打包后的js是一个有return的自执行函数,这个属性可以把这个函数赋值给指定的变量
        // libraryTarget: 'this',  // 指定上面赋值的方式,默认为var
      },
      plugins: [
        // 在打包文件中添加对应资源的dll文件 可以使用webpack自带模块DllReferencePlugin动态引入
        new webpack.DllPlugin({
          // 指定路径
          path: path.join(__dirname, './dist', '[name]-manifest.json'),
        // 指定依赖库的名称
          name: '_dll_[name]'
        }),
      ]
    }
    

    webpack.config.js

    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const webpack = require('webpack')
    const Happypack = require('happypack')
    module.exports = {
      entry: './src/index.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
    
      devServer: {
        port: 8080,
        open: true, // 自动打开浏览器
        contentBase: './dst', // 指定启动后默认访问的文件路径
      },
      module: {
        // webpack会在页面引入包时检测该包是否有需要的依赖,会消耗一部分时间
        noParse: /jquery/, // 设置不去解析是否有依赖的包以提高性能
        rules: [{
            test: /.\js$/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: [
                  '@babel/preset-env',
                  '@babel/preset-react'
                ]
              }
            }
            // 把对.js 的文件处理交给id为happyBabel 的HappyPack 的实例执行
            // use: 'Happypack/loader?id=js'
          },
          {
            test: /.\css$/,
            use: ['style-loader','css-loader']
            // use: 'Happypack/loader?id=css'
          }
        ]
      },
      plugins: [ // 数组 存放所有的webpack插件
        new HtmlWebpackPlugin({
          template: './src/index.html', // 模板
          filename: 'index.html', // 打包后文件名
        }),
        // 打包时忽略moment插件的语言文件
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
        new webpack.DllReferencePlugin({ // 引用存储在打包文件中的dll文件
          context: path.resolve(__dirname, '..'),
          manifest: require('./dist/main-manifest.json')
        }),
        new Happypack({
          // 用id来标识 happypack处理那里类文件
          id: 'js',
          use: [{
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-env',
                '@babel/preset-react'
              ]
            }
          }]
        }),
        new Happypack({
          // 用id来标识 happypack处理那里类文件
          id: 'css',
          use: ['style-loader','css-loader']
        }),
      ],
    }
    
    展开全文
  • 前言上一篇我们讲到,webpack3.x 升级 4.x 后打包大小优化,今天讲一下 webpack 4.x(webpack 4.43.0) 的打包速度优化,其实在升级了 webpack4 之后对于打包速度就已经有了很大的提升,但是查找时间(缩小范围)、...

    前言

    上一篇我们讲到,webpack3.x 升级 4.x 后打包大小优化,今天讲一下 webpack 4.x(webpack 4.43.0) 的打包速度优化,其实在升级了 webpack4 之后对于打包速度就已经有了很大的提升,但是查找时间(缩小范围)、loader 处理时间(多进程)、二次打包时间(缓存)仍有可优化的空间。

    打包分析

    在优化之前我们需要清楚项目打包的性能情况,这里我们使用 speed-measure-webpack-plugin 插件来进行分析

    webpack.base.js

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12+const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');

    +const smp = new SpeedMeasurePlugin({

    + outputFormat: 'humanVerbose'

    +});

    const webpackConfig = merge(baseWebpackConfig, {

    // ..

    });

    -module.exports = webpackConfig;

    +module.exports = smp.wrap(webpackConfig);

    打包看下,本次耗时 62,361 ms,列出了 Plugins 和 Loaders 具体耗时的细节:

    图比较长但是基本能看出,其中耗时较多的是 vue-loader 和 ts-loader

    1.jpg

    查找时间优化-exclude/include

    webpack 从入口文件开始,根据依赖关系查找模块,我们要尽可能少的处理模块,最常见的就是排除 exclude: /node_modules/,exclude 和 include 同时使用时 exclude 优先级更高

    webpack.base.js

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27module.exports = {

    module: {

    rules: [

    {

    test: /\.vue$/,

    loader: "vue-loader",

    },

    {

    test: /\.js$/,

    loader: "babel-loader",

    // 确保 node_modules 中 Vue 单文件组件的 部分能被转译

    exclude: (file) => /node_modules/.test(file) && !/\.vue\.js/.test(file),

    },

    {

    test: /\.tsx?$/,

    loader: "ts-loader",

    exclude: /node_modules/,

    options: {

    // 禁用类型检查,可以通过插件的方式使用

    transpileOnly: true,

    experimentalWatchApi: true,

    appendTsSuffixTo: [/\.vue$/],

    },

    },

    ],

    },

    };

    loader 处理时间优化-thread-loaderEach worker is a separate node.js process, which has an overhead of ~600ms. There is also an overhead of inter-process communication.

    每个 worker 都是一个单独的 node.js 进程,其开销约为 600 毫秒。进程间通信也有开销。查看更多

    webpack.base.js

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84// ...

    const isProduction = process.env.NODE_ENV === "production";

    if (isProduction) {

    const threadLoader = require("thread-loader");

    // 预热 worker

    threadLoader.warmup(

    {

    // pool options, like passed to loader options

    // must match loader options to boot the correct pool

    },

    [

    // modules to load

    // can be any module

    "babel-loader",

    "ts-loader",

    "vue-loader",

    "sass-loader",

    ]

    );

    }

    module.exports = {

    // ...

    module: {

    rules: [

    {

    test: /\.vue$/,

    use: isProduction ? ["thread-loader", "vue-loader"] : ["vue-loader"],

    },

    {

    test: /\.js$/,

    use: isProduction

    ? ["thread-loader", "babel-loader"]

    : ["babel-loader"],

    exclude: (file) => /node_modules/.test(file) && !/\.vue\.js/.test(file),

    },

    {

    test: /\.tsx?$/,

    loader: "ts-loader",

    exclude: /node_modules/,

    use: isProduction

    ? [

    "thread-loader",

    {

    loader: "ts-loader",

    options: {

    happyPackMode: true,

    transpileOnly: true,

    experimentalWatchApi: true,

    appendTsSuffixTo: [/\.vue$/],

    },

    },

    ]

    : [

    {

    loader: "ts-loader",

    options: {

    transpileOnly: true,

    experimentalWatchApi: true,

    appendTsSuffixTo: [/\.vue$/],

    },

    },

    ],

    },

    {

    test: /\.s?css$/,

    use: isProduction

    ? [

    MiniCssExtractPlugin.loader,

    "css-loader",

    {

    loader: "thread-loader",

    options: {

    workerParallelJobs: 2,

    },

    },

    "sass-loader",

    ]

    : ["vue-style-loader", "css-loader", "sass-loader"],

    },

    ],

    },

    };

    与 ts-loader 使用时报错1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11ERROR in ./src/main.ts

    Module build failed (from ./node_modules/thread-loader/dist/cjs.js):

    Thread Loader (Worker 0)

    Cannot read property 'errors' of undefined

    at PoolWorker.fromErrorObj (/Users/yourProjectPath/node_modules/thread-loader/dist/WorkerPool.js:262:12)

    at /Users/yourProjectPath/node_modules/thread-loader/dist/WorkerPool.js:204:29

    at mapSeries (/Users/yourProjectPath/node_modules/neo-async/async.js:3625:14)

    at PoolWorker.onWorkerMessage (/Users/yourProjectPath/node_modules/thread-loader/dist/WorkerPool.js:170:35)

    at successfulTypeScriptInstance (/Users/yourProjectPath/node_modules/ts-loader/dist/instances.js:119:28)

    at Object.getTypeScriptInstance (/Users/yourProjectPath/node_modules/ts-loader/dist/instances.js:34:12)

    at Object.loader (/Users/yourProjectPath/node_modules/ts-loader/dist/index.js:17:41)

    ts-loader 设置 happyPackMode: true,查看更多

    与 node-sass 使用

    看 webpack 文档有提到说 node-sass 搭配 thread-loader 使用的时候需要设置 workerParallelJobs: 2,亲测发现现在不用这样设置了,速度会快一些

    thread-loader@2.1.3 node-sass@4.13.1 node@12.16.2

    与 sass-loader 使用时报错

    报错信息如下:

    1

    2

    3Module build failed (from ./node_modules/thread-loader/dist/cjs.js):

    Thread Loader (Worker 3)

    this.getResolve is not a function

    暂时没有解决方案,将 sass-loader 降级到 v7.3.1 可以正常运行,相关 issue

    二次打包时间优化-cache

    使用 webpack4 二次打包的时候,我们会发现比第一次快来不少,这是因为 webpack 内置 terser-webpack-plugin 来最小化 JS 文件,默认会启用多进程和缓存,第二次的时候直接读取项目下 node_modules/.cache/terser-webpack-plugin 目录,所以较第一次打包会快上不少

    同样的我们在使用 babel-loader 的时候,也可以将缓存启用,设置 cacheDirectory: true 即可

    如果你想缓存其他 loader 的处理结果,你可以使用 cache-loader

    总结

    项目不够大,服务器逻辑核数(物理核心 * 每个核心的线程数)不够多,不要使用多进程打包,反向优化说的就是我,使用 thread-loader 多进程打包后,在本地构建反而增加了近 40s 的时间,如下图:

    2.jpg

    这篇文章拖了很久,半个多月才写完,总结一下拖延的点:

    一是中途看到【Webpack】538- 打包速度提升指南这篇文章,觉得写的很好,一度都不想开始优化了,觉得写了没别人写得好,还写出来干啥。后来硬着头皮优化完了,发现文章有过时(HappyPack)和冗余(terser-webpack-plugin 默认会启用 多进程)的部分,而且也没有实践的部分,顿时就觉得有了自己的(这篇文章)存在有了意义;

    二是发现优化完之后发现效果不好,在本地构建甚至反向优化,一度怀疑还有没有写的必要,好在在测试服务器上通过 CI/CD 构建速度中位数 50s 左右,还算可以,抱着有始有终的态度写完了

    最后还是提一下,worker 启动和进程间通信的开销都不小,结合项目实际情况使用,不要为了用而用,项目质量比性能更重要。

    参考链接

    展开全文
  • webpack打包速度优化

    2017-11-22 11:49:00
    打包速度优化 Webpack 默认提供的 UglifyJS 插件,由于采用单线程压缩,速度颇慢 ;推荐采用 webpack-parallel-uglify-plugin 插件,其做法如下, new webpack.optimize.UglifyJsPlugin({ compress: { warnings: ...
  • webpack4打包优化配置

    千次阅读 2019-05-31 10:11:37
    1、对图片进行压缩和...image-webpack-loader可以帮助我们对图片进行压缩和优化 cnpm install image-webpack- --save-dev 复制代码 { test: /\.(png|svg|jpg|gif|jpeg|ico)$/, use: [ 'file-loader', { loade...
  • 1、保证webpack、npm、node的版本比较新 ...resolve:{ // 配置模块如何被解析,能够提高webpack打包速度 alias: { // 配置别名,更容易引入 child: path.resolve(__dirname, '../src/child') ...
  • webpack打包优化速度

    千次阅读 2019-07-01 14:25:55
    在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在。 在配置 resolve.extensions 时你需要遵守以下几点,以做到尽可能的优化构建性能: 后缀尝试列表要尽可能的小,不要把项目中不可能...
  • 如何优化webpack打包速度

    千次阅读 2019-02-20 15:53:32
    文章目录前言怎么优化webpack打包速度有些其他方法对webpack的理解对webpack了解哪些webpack的打包原理webpack的构建流程参考文章 前言 今天面试遇到了一个问题,先问的是怎么理解webpack的,我答了webpack的主要...
  • webpack提升打包速度

    2020-06-11 22:06:36
    提升webpack打包速度的方法(1) 1.跟上技术迭代(node、npm 、yarn)更新到最新版本。(人家会优化内部) 2.在尽可能少的模块上应用Loader 3.Plugin尽可能精简并确保可靠 (尽可能少的使用) resolve参数合理配置...
  • Webpack 4 以及打包优化

    2019-05-09 15:36:33
    在上篇文章基础上...修改上次目录结构 需要下载的依赖package.js { "name": "webpack4-vue", "version": "1.0.0", "description": "", "main": "index.js"...
  • 2、方法二:uglifyjs-webpack-plugin 开启 parallel 参数 3、方法三:terser-webpack-plugin 开启 parallel 参数 optimization: { minimizer: [ new TerserPlugin({ parallel: true, cache: true }) ]...
  • 文档地址thread-loader · webpack 中文文档(v4.15.1) 可配选项 use: [ { loader: "thread-loader", // 有同样配置的 loader 会共享一个 worker 池(worker pool) options: { // 产生的 worker 的数量,默认...
  • 可选thread-loader或者 HappyPack或者parallel-webpack 2、多进程/多实例: 使用 HappyPack 解析资源 原理:每次 webapck 解析一个模块,HappyPack 会将它及它的依赖分配给 worker 线程中 const HappyPack...
  • webpack打包优化的目的 (1). 使打包的体积更小; (2). 使打包的速度更快; 1. 如何使打包的速度更快: (1). 用happypack提升项目的构建速度;happypack只作用在loader上,使用多个进程同时对文件进行编译处理; ...
  • webpack4.0打包优化策略

    2018-12-06 09:30:54
    webpack4.0打包优化策略(一) webpack4.0打包优化策略(二) webpack4.0打包优化策略(三) 提取公共代码与第三方代码 将多个入口重复加载的公共资源提取出来 相同的资源被重复的加载,浪费用户的流量和服务器的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,685
精华内容 3,874
关键字:

webpack4打包速度优化