webpack公共代码-Vue项目Webpack优化实践,建立效率提升50%

2023-09-04 0 5,705 百度已收录

公司后端项目使用Vue框架,Vue框架使用Webpack对其进行改进。 随着项目的不断迭代,项目逐渐变大,但项目的创建速度却急剧显得缓慢,因此迫切需要对Webpack创建进行优化。 经过不断探索和实践,通过以下方式优化后,项目创建速度提升了50%。 现在我们就总结分享一下相关的优化方法。

github地址为:github.com/fengshi123/...。 如果您喜欢或者觉得有启发,请给个star吧~,这也是对作者的鼓励。

1. 缩小文件搜索范围 1.1. 优化Loader配置

由于Loader的文件转换操作非常耗时,因此需要让Loader处理尽可能少的文件。 我们可以通过以下三个方面来优化Loader配置:(1)优化正则匹配(2)通过cacheDirectory选项启用缓存(3)通过include和exclusive减少正在处理的文件数量。 做法如下:

原始项目配置:

{
  test: /.js$/,
  loader: 'babel-loader',
  include: [resolve('src'), resolve('test')]
},

优化后配置:

{
  // 1、如果项目源码中只有js文件,就不要写成/.jsx?$/,以提升正则表达式的性能
  test: /.js$/,
  // 2、babel-loader支持缓存转换出的结果,通过cacheDirectory选项开启
  loader: 'babel-loader?cacheDirectory',
  // 3、只对项目根目录下的src 目录中的文件采用 babel-loader
  include: [resolve('src')]
},

1.2. 优化resolve.modules配置

resolve.modules 用于配置Webpack搜索第三方模块的目录。 resolve.modules的默认值是[nodemodules],意思是先去当前目录的/nodemodules目录下找到我们要找的模块。 如果没有找到,则去上层目录../nodemodules查找。 如果没有找到,就去那里。 ../../nodemodules,这样一来,这和Node.js的模块搜索机制非常相似。 当安装的第三方模块放在项目根目录的./nodemodules目录下时,不需要按照默认的方式逐层查找。 您可以指定第三方模块存储的绝对路径,以方便查找。

优化后配置:

resolve: {
// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
modules: [path.resolve(__dirname,'node_modules')]
},

1.3. 优化resolve.alias配置

webpack公共代码-Vue项目Webpack优化实践,建立效率提升50%

resolve.alias配置项通过别名将原导出路径映射到新的导出路径。

按照项目中的配置,使用:

alias: {
  '@': resolve('src'),
},
// 通过以上的配置,引用src底下的common.js文件,就可以直接这么写
import common from '@/common.js';

1.4. 优化resolve.extensions配置

当导出没有文件后缀的句子时,Webpack 会在手动添加后缀后尝试询问该文件是否存在。 默认为:扩展名:['.js','.json']。 也就是说,当遇到 require('./data') 这样的导出语句时,Webpack 会首先查找 ./data.js 文件。 如果该文件不存在,它将查找 ./data.json 文件。 如果还存在找不到的话就会报错。 如果列表较长,或者正确的后缀更靠前,就会导致更多的尝试,所以resolve.extensions的配置也会影响创建的性能。

优化措施:

• 后缀尝试列表应尽可能小,并且不要将项目中不太可能存在的情况纳入后缀尝试列表中。

•最常出现的文件后缀应首先放置在顶部,以便尽快退出搜索过程。

•在源代码中编写派生语句时,尽可能使用后缀,以避免搜索过程。例如,在某些情况下将 require('./data') 写为 require('./data.json') ,它可以与enforceExtension和enforceModuleExtension结合使用,强制开发者遵循这种优化。

1.5. 优化resolve.noParse配置

noParse 配置项可以让 Webpack 忽略对一些未模块化文件的递归解析和处理。 这用于提高创建性能。 原因是一些库(例如 jQuery 和 ChartJS)很复杂并且没有采用模块化标准。 Webpack 解析此类文件既耗时又无意义。 noParse 是可选配置项,类型必须是 RegExp、[RegExp] 和 function 之一。 例如,如果要忽略 jQuery 和 ChartJS,优化配置如下:

// 使用正则表达式 
noParse: /jquerylchartjs/ 
// 使用函数,从 Webpack3.0.0开始支持 
noParse: (content)=> { 
// 返回truefalse 
return /jquery|chartjs/.test(content); 
}

2.减少冗余代码

babel-plugin-transform-runtime是Babel官方提供的插件,用于减少冗余代码。 Babel 将 ES6 代码转换为 ES5 代码时,通常需要一些 ES5 编译的辅助函数来完成新句型的实现。 例如,在转换classextent句型时,它会在转换后的ES5代码中注入extent辅助函数来实现。 继承。 babel-plugin-transform-runtime 会将相关辅助函数替换为导出语句,从而减少 babel 编译代码的文件大小。

3.使用HappyPack多进程解析和处理文件

由于需要解析和处理的文件数量很大,因此创建是一个文件读取、写入和计算密集型操作。 尤其是当文件数量增多时,Webpack创建速度慢的问题会变得更加严重。 运行在 Node 上的 Webpack。 是单线程模型,这意味着Webpack需要一项一项地处理任务,无法同时处理多个任务。 HappyPack() 允许 Webpack 执行此操作。 它将任务划分为多个子进程并发执行。 子进程处理完成后,将结果发送给主进程。

HappyPack在项目中的使用配置:

(1)HappyPack插件安装:
    $ npm i -D happypack
(2)webpack.base.conf.js 文件对module.rules进行配置
    module: {
     rules: [
      {
        test: /.js$/,
        // 将对.js 文件的处理转交给 id 为 babel 的HappyPack实例
          use:['happypack/loader?id=babel'],
          include: [resolve('src'), resolve('test'),   
            resolve('node_modules/webpack-dev-server/client')],
        // 排除第三方插件
          exclude:path.resolve(__dirname,'node_modules'),
        },
        {
          test: /.vue$/,
          use: ['happypack/loader?id=vue'],
        },
      ]
    },
(3)webpack.prod.conf.js 文件进行配置    const HappyPack = require('happypack');
    // 构造出共享进程池,在进程池中包含5个子进程
    const HappyPackThreadPool = HappyPack.ThreadPool({size:5});
    plugins: [
       new HappyPack({
         // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
         id:'vue',
         loaders:[
           {
             loader:'vue-loader',
             options: vueLoaderConfig
           }
         ],
         threadPool: HappyPackThreadPool,
       }),
       new HappyPack({
         // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
         id:'babel',
         // 如何处理.js文件,用法和Loader配置中一样
         loaders:['babel-loader?cacheDirectory'],
         threadPool: HappyPackThreadPool,
       }),
    ]

4.使用ParallelUglifyPlugin在多进程中压缩代码文件

因为在压缩JavaScript代码时,需要先将代码解析成Object具体表示的AST句型树,然后利用各种规则对AST进行分析处理,这个过程需要巨大的计算量,需要花费大量的时间。 当Webpack有多个JavaScript文件需要输出压缩时,会使用UglifyJS将其一一压缩输出,ParallelUglifyPlugin会开启多个子进程,将多个文件的压缩工作分配给多个子进程来完成,各个子流程。 该过程可能仍然使用 UglifyJS 来压缩代码并并行执行。 因此,ParallelUglifyPlugin可以更快地完成多个文件的压缩。

项目中ParallelUglifyPlugin使用配置:

(1)ParallelUglifyPlugin插件安装:
     $ npm i -D webpack-parallel-uglify-plugin
(2)webpack.prod.conf.js 文件进行配置
    const ParallelUglifyPlugin =require('webpack-parallel-uglify-plugin');
    plugins: [
    new ParallelUglifyPlugin({
      cacheDir: '.cache/',
      uglifyJs:{
        compress: {
          warnings: false
        },
        sourceMap: true
      }
     }),
    ]

5.使用手动刷新

采用手动方式,当窃听本地源代码文件发生变化时,手动重新创建可执行代码,然后控制浏览器刷新。 Webpack将这个功能具体化了,提供了多种选项供我们选择。

项目中手动刷新配置:

devServer: {
  watchOptions: {
    // 不监听的文件或文件夹,支持正则匹配
    ignored: /node_modules/,
    // 监听到变化后等300ms再去执行动作
    aggregateTimeout: 300,
    // 默认每秒询问1000次
    poll: 1000
  }
},

相关优化措施:

(1)配置忽略一些没有被bug的文件,例如:node_modules。

(2)watchOptions.aggregateTirneout的值越大,性能越好,因为这样可以减少重建的频率。

(3)watchOptions.poll的值越小越好,因为这样可以提高检测的频率。

6. 启用模块热更换

DevServer还支持一种称为热模块替换(HotModuleReplacement)的技术,无需刷新整个网页即可实现超灵敏的实时预览。 原理是当源代码发生变化时,只需重新编译变化的模块webpack公共代码,然后用新输出的模块替换浏览器中对应的旧模块。 模块热替换技术极大提升了开发效率和体验。

项目中模块热插拔的配置:

devServer: {
  hot: true,
},
plugins: [
  new webpack.HotModuleReplacementPlugin(),
// 显示被替换模块的名称
  new webpack.NamedModulesPlugin(), // HMR shows correct file names
]

7. 提取公共代码

如果每个页面的代码都包含这个公共部分,就会导致以下问题:

webpack公共代码-Vue项目Webpack优化实践,建立效率提升50%

• 重复加载相同资源,浪费用户流量和服务器成本。

•每个页面需要加载的资源过大,导致网页首屏加载缓慢,影响用户体验。

如果将多个页面的公共代码提取到一个单独的文件中,则可以优化上述问题。 Webpack 有一个外部插件 CommonsChunkPlugin,用于提取多个 Chunks 的公共部分。

项目中CommonsChunkPlugin的配置:

// 所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。
new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function(module, count) {
    return (
      module.resource &&
      /.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, '../node_modules')
      ) === 0
    );
  }
}),
// 抽取出代码模块的映射关系
new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  chunks: ['vendor']
}),

8.按需加载代码

当使用Vue编写的单页面应用程序时,可能会有大量的路由导入。 创建包的时候webpack公共代码,javascript包会显得很大,影响加载。 如果我们能够将不同路由对应的组件划分到不同的代码块中,然后在访问路由时加载相应的组件,效率会更高。 这会大大提高首屏的显示速度,也可能会降低其他页面的速度。

项目西线按需加载(延迟加载)的配置:

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

9. 优化SourceMap

我们打包项目后,会将正在​​开发的多个文件的代码打包成一个文件,但经过压缩后,去掉多余的空格,经过babel编译后,最终会在wire和belt环境中使用。 这样处理后,代码和源码就会有很大的区别。 当出现bug时,我们只能定位压缩后的代码位置,而很难在开发环境中定位代码。 不利于开发,所以出现了sourceMap。 它旨在解决不良比例代码的问题。

SourceMap的可选值如下:

开发环境推荐:cheap-module-eval-source-map

推荐用于生产环境:cheap-module-source-map

原因如下:

1、源码中的列信息没有任何作用,所以我们打包的文件不想包含列相关的信息。 只有行信息才能完成打包前后的依赖关系。 因此,无论是开发环境还是生产环境,我们都希望添加廉价的基本类型来忽略打包前后的栏目信息。

2、无论是开发环境还是未来环境,我们都希望能够定位到bug源代码的具体位置。 比如某个vue文件报错,我们希望定位到具体的vue文件,所以我们还需要模块配置。

3.我们需要一种生成map文件的方法,所以我们需要减少source-map属性。

4.当我们介绍eval打包代码时,我们知道eval打包的速度非常快,因为它不生成map文件,并且可以将eval-source-map与eval结合使用。 使用eval会将地图文件以DataURL的形式保存并打包。 在后面的js文件中。 在直接环境中不要使用eval-source-map,因为它会减少文件大小,而在开发环境中,您可以尝试它,因为它们打包速度很快。

10、施工成果输出分析

Webpack输出的代码可读性非常差,而且文件很大,这让我们很头疼。 为了更加简单直观地分析输出结果,社区中出现了很多可视化分析工具。 该工具以图形的方式更加直观地展示结果,让我们能够快速了解​​问题。 接下来讲解一下vue项目中使用的分析工具:webpack-bundle-analyzer。

在项目中的webpack.prod.conf.js中配置:

if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin =   require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
执行 $ npm run build --report 后生成分析报告如下:

github地址为:github.com/fengshi123/...。 如果您喜欢或者觉得有启发,请给个star吧~,这也是对作者的鼓励。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 webpack webpack公共代码-Vue项目Webpack优化实践,建立效率提升50% https://www.wkzy.net/game/193329.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务