IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【实战篇】基于vue-cli创建的项目进行打包优化 -> 正文阅读

[JavaScript知识库]【实战篇】基于vue-cli创建的项目进行打包优化

一、前言

阅读完该文章大概需要2.5min。

  • 读完该篇文章你能学到

    1. vue-cli默认做了哪些优化?
    2. 在cli的基础上我们又能做哪些优化?
    3. vue.config.js中如何配置一些常用的pluginloader
  • vue-cli的出现,让我们省掉了配置webpack的时间。也就是说,一个不懂webpack的人,也能直接上手开发。比如file-loader, url-loader会提前为我们配置好。

  • 性能方面vue-cli也默认尽可能多的帮我们做了优化,比如cache-loader会在项目中预先做了配置。我们可以在控制台输入vue inspect > webpack.config.js,即可在webpack.config.js文件中查看cli预先定义好的基础配置。我们今天就在vue-cli搭建好的项目基础上聊一聊可优化的点。

二、项目源码

本文所用到的项目源码

三、量化指标

1. build时间

speed-measure-webpack-plugin插件可以在build的时候看到webpack的loader和plugin所用的时间,配置非常简单。如下:

// vue.config.js
module.exports = {
chainWebpack: config => {
   config.plugin('speed')
   .use(SpeedMeasureWebpackPlugin)
 }
}

顺便看一下效果
屏幕快照 2021-07-31 下午4.57.58.png

2.build后包的大小以及包的多少

webpack-bundle-analyzer插件可以帮我们可视化的展示build时的每个包的大小以及依赖。vue-cli也帮我们做了默认的配置,我只需要在build的后面加一个参数–report即可。

// package.json
{
  "name": "dll-vue",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "report": "vue-cli-service build --report",
  }
}

npm run report?之后,dist目录下就多了一个report.html文件,我们用浏览器打开这个文件看一下,右上角那个小蓝块是我们的vue代码,接下来我们主要来优化小蓝块之外的代码

屏幕快照 2021-07-31 下午9.51.03.png

四、开始优化

1. include/exclude

我们通常配置include和exclude,来达到使loader仅仅处理匹配到的文件,像这样

// webpack.config.js
module.exports = {
  module: { 
      rules: [ 
          { 
              test: /\.js[x]?$/, 
              use: ['babel-loader'], 
              include: [path.resolve(__dirname, 'src')] 
          }
         ] 
  },
}

而vue的transpileDependencies属性默认情况下?babel-loader?会忽略所有?node_modules?中的文件,其实已经满足了我们大部分需求。

2. resolve

resolve: 配置?webpack如何寻找模块所对应的文件,比如import * from ‘xxx’,xxx模块应该优先从node_modules中找,我们通过vue inspect > webpack.config.js导出的文件中在modules字段中可以清晰的看到已经将node_modules设置为优先寻找的模块

resolve: {
    // ...
    modules: [
      'node_modules',
      ...
    ]
    // ...
 }

3. happypack-plugin/thread-loader

一般来说,我们可以通过happack-plugin或者thread-loader开启多线程打包。vue-cli的parallel属性的含义是:是否为 Babel 或 TypeScript 使用?thread-loader,默认值为cpu的内核数,也就是说如果你系统是3核cpu,则build的时候,会自动在babel-loader和ts-loader执行时候开启3个线程。如果你想试着自己的配置一下,可以像下面这样。(不过我试着自己配置了之后,似乎没什么效果。也许是我配置的不对,欢迎大家来指正)

config.module.rule('vue')
          .use('thread-loader')
          .loader('thread-loader')
          .before('vue-loader')

4. noParse

如果一些第三方模块没有AMD/CommonJS规范版本,可以使用?noParse?来标识这个模块,这样?Webpack?会引入这些模块,但是不进行转化和解析,从而提升?Webpack?的构建性能 ,例如:jquery?、lodash,vue.config.js中可以这样配置:

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
    module: {
      noParse: /^(lodash|moment)$/
    }
  }
  //...
}

5. ContextReplacementPlugin

一些依赖,我们也许只是用到了一部分,没必要全部解析,比如moment中的语言包,我们一般只用中文包就够了,所以可以这样配置:

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
       plugins: [
           new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn/)
       ]
  }
  //...
}

我们通过一张图片来体验一下, 左边为去掉语言包的效果

moment.png

6. externals

一般来说像jQuery这些第三方的包,我们采用CDN的方式来引入,像这样

<-- public/index.html -->
<script src="https://code.jquery.com/jquery-3.6.0.min.> js"></script>

在使用的时候,我们希望通过import的方式引入,像这样

// App.vue\
import $ from 'jquery'
$('.today').text = 'today'

这就造成一个问题,build的时候就会将jquery再打包一次 我们可以配置externals来达到build时忽略掉指定的依赖

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
    config.externals = {
      jquery: 'jQuery'
    }
  }
  //...
}

7. uglifyjs-webpack-plugin

在build的时候可以压缩代码的大小,有几个常用的配置可以单独提一下,比如去掉console.log,比如进行多进程压缩。可以这样:

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
    config.optimization.minimizer = [
      new UglifyJsPlugin({
       uglifyOptions: {
        compress: {
         drop_console: true, // 去掉console
        }
        parallel: true, //默认并发运行数:os.cpus().length - 1
       }
      })
     ]
  }
  //...
}

8. compression-webpack-plugin

我们可以将代码压缩为.gz文件,浏览器也是可以识别的。可以这样配置

//vue.config.js
module.exports = {
   //...
   configureWebpack:{
    plugins: [
        new CompressionWebpackPlugin()
    ]
  }
  //...
}

9. DllPlugin 和 DllReferencePlugin

  • 对于变化几率很小的一些第三方包,其实没必要build的时候都要打包一次, 可以把这些第三方包单独抽离出来,提前打包好。
  • webpack本身是要体现出模块间的依赖关系,当我们将一些包抽离出来后,维护之前的依赖关系就需要manifest.json这个文件。让我们从接下来的实战中来学习它。

<1> 新建一个配置文件webpack.dll.config.js

// webpack.dll.config.js
module.exports = {
  mode: 'production',
  entry: {
    vue_vendor: ['vue/dist/vue.runtime.esm.js', 'vuex',  'vue-router', 'element-ui'],
    other_vendor: ['lodash', 'moment']
  },
  output: {
    filename: '[name].dll.js',
    path: path.resolve(__dirname, './public/dll'),
    library: '[name]_[hash]'
  },\
  plugins: [
    new webpack.DllPlugin({
      name: '[name]_[hash]',
      path: path.resolve(__dirname, '[name].manifest.json')
    })
  ]
}

<2> 为了方便,我们将读取该配置文件的命令写到package.json文件中,像这样。(需要安装webpack-cli)

// package.json
{
  .....
  "scripts": {
    .....
    "dll": "webpack --config ./webpack.dll.config.js"
  }
  .....
}

<3> 执行npm run dll后可以看到生成两个manifest文件,像这样

屏幕快照 2021-08-02 下午8.06.25.png

<4> 修改vue.config.js,引入依赖文件,并自动将dll下的文件插入到index.html中(这里我们引入一个插件add-asset-html-webpack-plugin

module.exports = {
  chainWebpack: config => {
    // 多个manifest.json文件就需要写多次
    config.plugin('vendorDll1')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifest: require('./public/manifest/other_vendor.manifest.json')
      }
    ])

    config.plugin('vendorDll2')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifest: require('./public/manifest/vue_vendor.manifest.json')
      }
    ])

    // 将dll下的文件自动插入到index.html中
    config.plugin('asset')
    .use(AddAssetHtmlWebpackPlugin, [
      [
        {
          filepath: path.resolve(__dirname, 'public/dll/vue_vendor.dll.js'),
          outputPath: 'dll',
          publicPath: '/dll'
        },
        {
          filepath: path.resolve(__dirname, 'public/dll/other_vendor.dll.js'),
          outputPath: 'dll',
          publicPath: '/dll'
        }
      ]
    ])
  }
}

10. optimization.splitChunks

抽离公共代码,通过配置splitChunks可抽离公共的代码,防止重复,我没有在自己的项目中用,

//vue.config.js
module.exports = {
   //...
   chainWebpack: config => {
      config.optimization.splitChunks({
          chunks: 'all',
          cacheGroups: {}
      })
   }
  //...
}

五、效果展示

section1.png

section2.png

all.png

六、补充几个不需要配置的优化点

1. extensions

当我们导入模块时,假如没有指定后缀,期望优先匹配的文件格式,我们直接看vue-cli默认的配置extensions: ['.mjs', '.js', '.jsx', '.vue', '.json', '.wasm']

2. tree-shaking

我们通过import方式引入,webpack会自动移除掉没有用到的模块代码

3. Scope hosting

作用域提升:比如

let a = 1
let b = 2
let c = a + b

// webpack自动优化为
c = 3

4. 路由懒加载

通过() => import(‘xxx’)方式引入,可达到路由懒加载的效果

六、总结

  • 该文章为最近优化团队项目的webpack打包速度,做的总结。

  • 如果有不对的地方欢迎大家在讨论区纠正

  • 欢迎关注公众号:前端小卡

  • 如果觉得有用,欢迎点个赞啦

展开阅读全文
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-03 11:05:05  更:2021-08-03 11:07:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 4:35:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码