如何更好的进行webpack的打包优化

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 在前面的一篇文章里提到了,现有项目的升级,但升级结束并不意味这整个任务的结束。还有针对项目打包速度的提升,当一个vue的项目页面在200以上的时候,这个打包速度就会大幅度的降低。那么针对webpack的打包优化就是一件不得不做的事情了,webpack打包优化分为两部分,一部分是大小优化,另一部分是速度优化。

大小优化

1.Externals

webpack 提供Externals的方法,可以通过外部引用的方法,引入第三方库: index.html

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

webpack.base.conf.js

 //webpack.base.conf.js
 externals: {
 包名 全局名称---支持驼峰
 'vue-router': 'VueRouter',
 'echarts': 'echarts',
 "axios":"axios",
 "jquery": 'jQuery'
 },

业务逻辑,如index.js

import $ from 'jquery';
$('.my-element').animate(...);

webpack打包时,发现jquery定义在externals,则不会打包jquery代码。由于不需要打包jquery,所以也减少打包时间。 不过externals虽然解决了外部引用问题,但是无法解决以下问题:

import xxx from 'vue/src/xx';

webpack遇到此问题时,会重新打包vue代码。

2.DLL & DllReference

相比于前者,通过前置这些依赖包的构建,来提高真正的build和rebuild构建效率。也就是说只要第三方库没有变化,之后的每次build都只需要去打包自己的业务代码,解决Externals多次引用问题。 webpack通过webpack.DllPlugin与webpack.DllReferencePlugin两个内嵌插件实现此功能。

1、在build文件下新建webpack.dll.conf.js

const path = require('path')
const webpack = require('webpack')
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
    entry: {
        vendor: [
            'vue-router',
            'vuex',
            'vue',
            'axios',
            'echarts',
            'element-ui',
            'vx-easyui'
        ]
    },
    output: {
        path: path.resolve('../dist'),
        filename: '[name].dll.js',
        library: '[name]_library'
    },
    plugins: [
        new webpack.DllPlugin({
            path: path.resolve('../dist', '[name]-manifest.json'),
            name: '[name]_library'
        })
    ],
    optimization: {
        minimizer: [
            new TerserPlugin({
                cache: true, // 开启缓存
                parallel: true, // 支持多进程
                sourceMap: true,
            }),
        ]
    }
}

webpack.DllPlugin选项:

  • path:manifest.json文件的输出路径,这个文件会用于后续的业务代码打包;
  • name:dll暴露的对象名,要跟output.library保持一致;
  • context:解析包路径的上下文,这个要跟接下来配置的 webpack.config.js 一致。

在在build文件夹下的webpack.prod.conf文件中使用动态链接库文件

  • 在 webpack.prod.conf.js 的 plugin 后面加入配置
plugins: [
    new webpack.DllReferencePlugin({
      context: '.',
      manifest: require('../dist/vendor-manifest.json')
    })
]  

webpack.DllReferencePlugin的选项中:

  • context:需要跟之前保持一致,这个用来指导webpack匹配manifest.json中库的路径;
  • manifest:用来引入刚才输出的manifest.json文件。

将动态链接库文件加载到页面中

  • 根目录下的入口 index.html 加入引用

在这里插入图片描述

  • 根目录下package.json的script里加入快捷命令

在这里插入图片描述

  • 再次打包时可能会提示css文件语法的错误,这个时候可以将css的处理代码先注释掉。在build文件夹下的webpack.prod.conf.js 中的 plugin 里找到下面的内容进行注释

在这里插入图片描述

  • 要生成dll时运行npm run build:dll,即生成dist目录下两个文件 vender-manifest.jsonvender.dll.js。然后正式生成 prod npm run build,即生成除webpack.dll.config.js`中指定包之外的其他打包文件。

3.开启gzip

安装最新版的compression-webpack-plugin

npm i compression-webpack-plugin@5.0.0 -D

去config/index.js中找到

productionGzip:false
改为
productionGzip:true

webpack.prod.conf.js中修改

new CompressionWebpackPlugin({
  asset: '[path].gz[query]',
  algorithm: 'gzip',
  test: new RegExp(
    '\\.(' +
    config.build.productionGzipExtensions.join('|') +
    ')$'
  ),
  threshold: 10240,
  minRatio: 0.8
})
//改为
new CompressionWebpackPlugin({
  filename: info => {
    return `${info.path}.gz${info.query}`
  },//返回新资源文件名
  algorithm: 'gzip',
  threshold: 10240, //只处理比这个字节大的资源
  test: /\.(js|css|json|txt|html|ico|svg|png|eot|ttf|mp4|gif)(\?.*)?$/i,//类型为正则
  minRatio: 0.8, //只有压缩率比这个值小的资源才会被处理
  deleteOriginalAssets: true //是否删除原资源
})

速度优化

1.优化loader配置

1.1 缩小文件匹配范围(include/exclude)

通过排除node_modules下的文件 从而缩小了loader加载搜索范围 高概率命中文件\
module: {
  rules: [
    {
      test: /\.js$/,
      use: 'babel-loader',
      exclude: /node_modules/, // 排除不处理的目录
      include: path.resolve(dirname, 'src') // 精确指定要处理的目录
    }
  ]
}

1.2 缓存loader的执行结果(cacheDirectory)

cacheDirectory是loader的一个特定的选项,默认值是false。指定的目录(use: ‘babel-loader?cacheDirectory=cacheLoader’)将用来缓存loader的执行结果,减少webpack构建时Babel重新编译过程。如果设置一个空值(use: ‘babel-loader?cacheDirectory’) 或true(use: ‘babel-loader?cacheDirectory=true’) 将使用默认的缓存目录(node_modules/.cache/babel-loader),如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。

打开build文件夹下的webpack.base.conf.js文件,针对js的处理进行缓存
在这里插入图片描述

2.resolve优化配置

2.1 优化模块查找路径 resolve.modules

Webpack的resolve.modules配置模块库(即 node_modules)所在的位置,在 js 里出现 import ‘vue’ 这样不是相对、也不是绝对路径的写法时,会去 node_modules 目录下找。但是默认的配置,会采用向上递归搜索的方式去寻找,但通常项目目录里只有一个 node_modules,且是在项目根目录,为了减少搜索范围,可以直接写明 node_modules 的全路径;同样,对于别名(alias)的配置,亦当如此:
const path = require('path');
function resolve(dir) { // 转换为绝对路径
  return path.join(dirname, dir);
}
resolve: {
  modules: [ // 优化模块查找路径
    path.resolve('src'),
    path.resolve('node_modules') // 指定node_modules所在位置 当你import 第三方模块时 直接从这个路径下搜索寻找
  ]
}

配置好src目录所在位置后,由于util目录是在src里面 所以可以用下面方式引入util中的工具函数

// main.js
import dep1 from 'util/dep1';
import add from 'util/add';

2.2 resolve.alias 配置路径别名

创建 import 或 require 的路径别名,来确保模块引入变得更简单。配置项通过别名来把原导入路径映射成一个新的导入路径 此优化方法会影响使用Tree-Shaking去除无效代码。
例如,一些位于 src/ 文件夹下的常用模块

alias: {
 Utilities: path.resolve(dirname, 'src/utilities/'),
 Templates: path.resolve(dirname, 'src/templates/')
}

现在,替换「在导入时使用相对路径」这种方式,就像这样:

import Utility from '../../utilities/utility';

import Utility from 'Utilities/utility';

resolve: {
  alias: { // 别名配置 通过别名配置 可以让我们引用变的简单
    'vue$': 'vue/dist/vue.common.js', // $表示精确匹配
    src: resolve('src') // 当你在任何需要导入src下面的文件时可以 import moduleA from 'src/moduleA' src会被替换为resolve('src') 返回的绝对路径 而不需要相对路径形式导入
  }
}

也可以在给定对象的键后的末尾添加 $,以表示精准匹配:

alias: {
  util$: resolve('src/util/add.js')
}

这将产生以下结果:

import Test1 from 'util'; // 精确匹配,所以 src/util/add.js 被解析和导入
import Test2 from 'util/dep1.js'; // 精确匹配,触发普通解析 util/dep1.js

2.3resolve.extensions

当引入模块时不带文件后缀 webpack会根据此配置自动解析确定的文件后缀
后缀列表尽可能小
频率最高的往前放
导出语句尽可能带上后缀

3.ParallelUglifyPlugin

这个插件可以帮助有很多入口点的项目加快构建速度。把对JS文件的串行压缩变为开启多个子进程并行进行uglify。

cnpm i webpack-parallel-uglify-plugin -D
// webpck.config.js
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
plugins: [
  new ParallelUglifyPlugin({
    workerCount: 4,
    uglifyJS: {
      output: {
        beautify: false, // 不需要格式化
        comments: false // 保留注释
      },
      compress: { // 压缩
        warnings: false, // 删除无用代码时不输出警告
        drop_console: true, // 删除console语句
        collapse_vars: true, // 内嵌定义了但是只有用到一次的变量
        reduce_vars: true // 提取出出现多次但是没有定义成变量去引用的静态值
      }
    }
  });
]
相关文章
|
3月前
|
缓存 前端开发 数据可视化
Webpack Bundle Analyzer:深入分析与优化你的包
Webpack Bundle Analyzer是一款可视化工具,帮助分析Webpack构建结果,找出占用空间较大的模块以便优化。首先需安装Webpack和Webpack Bundle Analyzer,接着在`webpack.config.js`中配置插件。运行Webpack后,会在`dist`目录生成`report.html`,展示交互式图表分析包大小分布。为优化可采用代码分割、Tree Shaking、压缩插件、加载器优化、模块懒加载、代码预热、提取公共库、使用CDN、图片优化、利用缓存、避免重复模块、使用Source Maps、优化字体和图标、避免全局样式污染以及优化HTML输出等策略。
132 3
|
14天前
|
缓存 前端开发 JavaScript
前端性能优化:Webpack与Babel的进阶配置与优化策略
【10月更文挑战第28天】在现代Web开发中,Webpack和Babel是不可或缺的工具,分别负责模块打包和ES6+代码转换。本文探讨了它们的进阶配置与优化策略,包括Webpack的代码压缩、缓存优化和代码分割,以及Babel的按需引入polyfill和目标浏览器设置。通过这些优化,可以显著提升应用的加载速度和运行效率,从而改善用户体验。
35 6
|
16天前
|
缓存 监控 前端开发
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第26天】前端工程化是现代Web开发的重要趋势,通过将前端代码视为工程来管理,提高了开发效率和质量。本文详细对比了Webpack和Gulp两大主流构建工具的选择与配置优化,并提供了具体示例代码。Webpack擅长模块化打包和资源管理,而Gulp则在任务编写和自动化构建方面更具灵活性。两者各有优势,需根据项目需求进行选择和优化。
46 7
|
15天前
|
缓存 前端开发 JavaScript
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第27天】在现代前端开发中,构建工具的选择对项目的效率和可维护性至关重要。本文比较了Webpack和Gulp两个流行的构建工具,介绍了它们的特点和适用场景,并提供了配置优化的最佳实践。Webpack适合大型模块化项目,Gulp则适用于快速自动化构建流程。通过合理的配置优化,可以显著提升构建效率和性能。
29 2
|
2月前
|
JavaScript
webpack打包TS
webpack打包TS
132 60
|
1月前
|
缓存 前端开发 JavaScript
Webpack 打包的基本原理
【10月更文挑战第5天】
|
1月前
|
前端开发 JavaScript
ES6模块化和webpack打包
【10月更文挑战第5天】
|
1月前
|
缓存 前端开发 JavaScript
深入了解Webpack:模块打包的革命
【10月更文挑战第11天】深入了解Webpack:模块打包的革命
|
2月前
|
JavaScript 测试技术 Windows
vue配置webpack生产环境.env.production、测试环境.env.development(配置不同环境的打包访问地址)
本文介绍了如何使用vue-cli和webpack为Vue项目配置不同的生产和测试环境,包括修改`package.json`脚本、使用`cross-env`处理环境变量、创建不同环境的`.env`文件,并在`webpack.prod.conf.js`中使用`DefinePlugin`来应用这些环境变量。
98 2
vue配置webpack生产环境.env.production、测试环境.env.development(配置不同环境的打包访问地址)
|
29天前
|
缓存 前端开发 JavaScript
Webpack技术深度解析:模块打包与性能优化
【10月更文挑战第13天】Webpack技术深度解析:模块打包与性能优化