Webpack优化项目的七种方法,满满的干货

不说废话

一.预获取,预加载
在这里插入图片描述

举个例子,比如一个js文件,你项目开启的时候,等你发出某个指令的时候,那个文件js才加载

但是有一个问题,当你发出指令时候,首先要下载这个js文件,然后浏览器再解析这个文件,如果这个文件很大的话,肯定会有一定的延迟,页面才有效果

OK,先说Prefetch,通俗的来讲就是当你打开项目的时候,这个文件不会加载,等你的浏览器有空闲的时候,它自动帮你把这个文件下载下来,这样当你需要这个文件的时候,你就可以省去第一步下载这个js文件的时间了,就提升了性能

举个例子,点击button的时候,加载我们的element.js文件

具体代码实现

/**/里面的是魔法注释,并不是真正的注释

const button = document.createElement("button");
button.innerHTML = "加载元素";
button.addEventListener("click", () => {
  import(
    /* webpackChunkName: 'element' */
    /* webpackPrefetch: true */
    "./element"
  ).then(({default: element}) => {
    document.body.appendChild(element);
  })
});
document.body.appendChild(button);

效果如下:

在这里插入图片描述

再说Preload,它其实跟Prefetch的作用差不多,区别就是它是跟我们的父脚本一起下载的,也就是包含它的js文件加载的时候,它就跟着一起加载了,不过我们在浏览器的调试中,看不到它的变化,不过它确实是起效果了

具体代码实现

扫描二维码关注公众号,回复: 12972379 查看本文章
const button = document.createElement("button");
button.innerHTML = "加载元素";
button.addEventListener("click", () => {
  import(
    /* webpackChunkName: 'element' */
    /* webpackPreload: true */
    "./element"
  ).then(({default: element}) => {
    document.body.appendChild(element);
  })
});
document.body.appendChild(button);

下面总结一下它们两个的不同之处

1.preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。

2.preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。

3.preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。

4.浏览器支持程度不同。

二.CDN

在这里插入图片描述
缺点是,CDN服务器需要花钱买,不过也有免费的
好处是,当你使用CDN引入一些库和插件的时候,它不会被打包到你的项目当中,优化了性能

举个例子,我们使用lodash这个插件

index.html中

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

然后去我们的webpack配置里面

  externals: {
    lodash: "lodash",
  },

然后在项目中就可以使用了,打包时候不会打包这个文件

如果你在本地觉得这样影响调试的话,你可以通过ejs来判断一下环境

  <% if (process.env.NODE_ENV === 'production') { %> 
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
  <% } %> 

开发环境直接用npm的,生产环境再用cdn的

三.Tree Shaking

这个东西的作用就是,当你项目在打包的时候,它会帮你剔除一些无用的js代码,从而降低包的体积,提升性能

在这里插入图片描述
先说usedExports怎么实现

usedExports需要结合Terser来一起实现

usedExports: 目的是标注出来哪些函数是没有被使用 unused

terser:将未使用的函数, 从我们的代码中删除

具体代码如下:

optimization: {
    usedExports: true, // production
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
        extractComments: false,
        terserOptions: {
          compress: {
            arguments: false,
            dead_code: true
          },
          mangle: true,
          toplevel: true,
          keep_classnames: true,
          keep_fnames: true
        }
      })
    ]
  },

再说sideEffects

sideEffects的作用就是用于告知webpack compiler哪些模块是有副作用的

举个例子

比如你import了一个js文件,但是实际上你并没有用到这个js文件,但是你打包的时候还是会打包

那么如何解决呢?

直接到我们的package.json里面,加一个sideEffects等于false即可

在这里插入图片描述
但是还有一个问题,比如你有的js文件想打包的时候给它剔除,有的js文件,你里面有全局变量,不想给它剔除,那咋办呢??

这样写,把你不想剔除的js文件,写入到里面去

在这里插入图片描述
这样,打包的时候,你的a.js文件就不会被剔除,而你没有写入这个数组的js文件就会被剔除

但是一些引入的css文件也会被剔除,咋办呢?

在这里插入图片描述
这样写就好了

个人建议,最好写一些纯模块,这样直接把sideEffects设置为 false比较好

但是sideEffects设置为 false了,引入的css文件也会被剔除,咋办呢,好解决,去我们的webpack配置

在这里插入图片描述
给它加一个sideEffects: true就好了

总结一下:在我们真实的项目当中如何设置tree shaking

在这里插入图片描述
在react脚手架里面css有对sideEffects进行配置,vue里面好像没有,可能需要配置一下

四.purgeCSS

上面那个tree shaking是针对于我们的js代码,如何要对我们的css代码进行tree shaking的话,就要用到这个purgeCSS库

首先就是安装了

npm i purgecss-webpack-plugin -D

首先我们封装一个查找路径的方法

const path = require('path');

// node中的api
const appDir = process.cwd();
const resolveApp = (relativePath) => path.resolve(appDir, relativePath);

module.exports = resolveApp;

然后去配置我们的webpack

const glob = require('glob');
const resolveApp = require('./paths');

//假设我们所有的项目代码都在src目录下
plugins: [
      paths: glob.sync(`${resolveApp("./src")}/**/*`, {nodir: true}),
    })
  ]

如果你想让一些标签的样式不被删掉,这样写

 new PurgeCssPlugin({
      paths: glob.sync(`${resolveApp("./src")}/**/*`, {nodir: true}),
      safelist: function() {
        return {
          standard: ["body", "html"]
        }
      }
   })

body和html的样式,打包时候就不会被删掉

说明一下:如果你们使用less,scss写的css,tree shaking也会生效,它是对打包后的css进行tree shaking操作的

五.Gzip压缩

项目正常打包部署,直接在服务端对nginx配置进行修改。这样设置时,当你请求时,服务端就会先将对应的文件压缩成.gz格式再发送给你,客户端接收到了.gz文件的格式之后再解压并执行后续操作。相当于用压缩的时间,换取了文件传输的时间,通常都会是正优化,除非项目体积过小。

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    # 开启gzip
    gzip  on;
    
    # 设置缓冲区大小
    gzip_buffers 4 16k;
    
    #压缩级别官网建议是6
    gzip_comp_level 6;
 
    #压缩的类型
    gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php;


    server {
        listen       8462;
        server_name  localhost;

        location / {
            root   dist;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

项目打包时对webpack进行特殊设置,安装插件(compression-webpack-plugin);打包同时生成成两份文件,第一份为正常的文件,另一个为gz压缩后的文件,部署时将其全部部署至服务端。

const CompressionPlugin = require('compression-webpack-plugin');
module.exports= {
    configureWebpack: {
        plugins: [
            new CompressionPlugin({
                algorithm: 'gzip', // 使用gzip压缩
                test: /\.js$|\.html$|\.css$/, // 匹配文件名
                filename: '[path].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)
                minRatio: 1, // 压缩率小于1才会压缩
                threshold: 10240, // 对超过10k的数据压缩
                deleteOriginalAssets: false, // 是否删除未压缩的源文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false(比如删除打包后的gz后还可以加载到原始资源文件)
            })
        ],
    },
}

之后在nginx配置中使用:gzip_static on,该属性能够静态加载本地的gz文件,这样就完成了gzip。另外注意一下,如果我们的一个css或者js文件,里面的内容太少了,它是不会压缩这个文件的

六.InlineChunkHtmlPlugin

在这里插入图片描述
就相当于把我们的一些js代码,直接内嵌到html,当我们的html加载的时候,会一起把这些js文件加载,但是也会增加我们的html的体积

首先安装两个插件

npm i react-dev-utils -D
npm i html-webpack-plugin -D

然后配置我们的webpack

const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

//a表示我们要注入的js文件名,根据你的实际命名来
 plugins: [
    new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/a.*\.js/,])
  ]

七.webpack-bundle-analyzer

这个插件可以看见你项目打包之后,哪些文件过大,然后你自己进行代码的优化

在这里插入图片描述
首先安装插件

 npm i webpack-bundle-analyzer -D

然后在scripts中

"analyzer": "use_analyzer=true npm run serve",

再去webpack

module.exports ={
  chainWebpack: config => {
    if (process.env.use_analyzer) {    
        config
            .plugin('webpack-bundle-analyzer')
            .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
    }
},
}

之后运行

npm run analyzer

猜你喜欢

转载自blog.csdn.net/weixin_45389051/article/details/114550562
今日推荐