webpack生产环境优化-优化代码运行的性能

1.资源缓存:【作用:让代码上线运行缓存更好使用】

修改文件名后面带有hash值:.[hash:10]:每次webpack打包成功都会生成唯一hash值

问题:css和js文件同时使用一个hash值,如果只修改了css文件,重新打包的话会导致js文件的缓存失效

chunkhash:.[chunkhash:10]:根据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值一样。(在js中引入css文件的话,打包后同属于一个chunk),所以,如果只修改了css文件,重新打包的话会导致js文重新加载

contenthash:.[contenthash:10] 根据文件内容生成hash值,不同的文件hash值不一样,就可以解决上面的问题

 2、tree shaking移除 JavaScript 上下文中的未引用代码(dead-code),减少代码体积。

你可以将应用程序想象成一棵树。绿色表示实际用到的 source code(源码) 和 library(库),是树上活的树叶。灰色表示未引用代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。

使用:

  • 使用 ES2015 模块语法(即 import 和 export)。
  • 确保没有编译器将您的 ES2015 模块语法转换为 CommonJS 的(顺带一提,这是现在常用的 @babel/preset-env 的默认行为,)。
  • 在项目的 package.json 文件中,添加 "sideEffects" 属性。
  • 使用 mode 为 "production" 的配置项以启用更多优化项,包括压缩代码与 tree shaking。
"sideEffects": false

上述配置代表所有代码都没有副作用,都可以进行tree shaking,但是会把css/@babel/polyfill文件干掉

所以需要修改配置为:写在数组中的文件不会被tree shaking

"sideEffects": ["*.css"]

3、code split:代码分割

方式一:配置多个入口文件,一个入口会对应输出一个bundle 

module.exports = {
    entry:{
        index: './src/js/index.js',
        test: './src/js/test.js'
    },
    output:{
        filename: 'js/[name].[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
}

缺点:不太灵活,

方式二:可以将node_modules中的代码单独打包一个chunk最终输出【vue-cli默认打包就是这样的】;

module.exports = { 
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
}

多入口文件下,假如两个js文件同时引入了jquery,以上配置会最终打包成一个jquery的chunk,否则会打包两份。也就是说它可以分析多入口chunk中有没有公共的文件(文件体积稍大的),如果有的话会打包成单独一个chunk

方法三:[一般使用这种方法]

import动态导入语法:能将某个文件单独打包成一个chunk

import(/* webpackChunkName: 'test' */'./test')
    .then(({mul, count}) => {
     console.log(mul(2. 5));
    })
    .catch(() => {
     console.log('文件加载失败')
    })

4.lazy loading懒加载:对js进行懒加载

现有两个js文件,index.js和test.js,当点击按钮的时候再加载test.js文件,

懒加载示例

5.预加载:prefetch,会在使用之前提前加载js文件

页面初始化时network中可以看到加载了test.js文件,点击按钮的时候会读取缓存,重新加载js文件

那么疑问来了,既然预加载会直接加载js文件,为什么还要放在函数里呢,和被注释掉的代码有什么却别呢?

预加载:会在浏览器加载完其他文件后,空闲的时候再偷偷加载文件,相对于懒加载的好处是,当要加载的文件体积较大时 会造成用户体验不。但是预加载的兼容性较差,甚用!

6.PWA:渐进式网络开发应用程序 让项目变成离线也可以访问的效果

1.安装插件

npm install workbox-webpack-plugin --save-dev

2.引入插件并使用,插件会帮我们生成一个service-worker 配置文件


 const WorkboxPlugin = require('workbox-webpack-plugin');

  module.exports = {
    plugins: [
     new WorkboxPlugin.GenerateSW({
       // 这些选项帮助快速启用 ServiceWorkers
       // 不允许遗留任何“旧的” ServiceWorkers
       clientsClaim: true,
       skipWaiting: true,
     }),
    ],
  };

3.在入口文件中注册service work

 if ('serviceWorker' in navigator) {
   window.addEventListener('load', () => {
     navigator.serviceWorker.register('/service-worker.js').then(registration => {
       console.log('SW registered: ', registration);
     }).catch(registrationError => {
       console.log('SW registration failed: ', registrationError);
     });
   });
 }

4.service work代码必须运行在服务器上,我们可以借助插件来实现:

a.安装:

npm install http-server --save-dev

b.修改 package.json 的 scripts 部分,来添加一个 start script:

dist是我们打包后的文件夹

{
  ...
  "scripts": {
    "build": "webpack",
    "start": "http-server dist"
  },
  ...
}

c.运行命令就启动服务器啦 

npm start

 打开页面,可以观察application中的service workers、cache storage模块

把浏览器的network调成offline,刷新页面就可以验证了 

7.externals:防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)

例如index.html中引入的jquery是从cdn上引入的

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"
></script>

webpack.config.js

module.exports = {
  //...
  externals: {
    // 拒绝jquery被打包进来
    jquery: 'jQuery',
  },
};

8.DLL:动态链接库,

安装插件:dll-reference-plugin、add-asset-html-plugin

a.创建webpack.dll.js文件:使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包

const webpack = require('webpack')
const path = require('path')

module.exports = {
  entry: {
    // 最终打包生成的名称:要打包的库
    react: ['react', 'react-dom']
  },
  output: {
    library:  'react', // 以一个库的形式导出
    filename: '[name].dll.js'
  },
  plugins: [
    // 打包生成一个mainfest.json->提供和react映射
    new webpack.DllPlugin({
      name: 'react', // 映射库的暴露的内容名称
      path: path.resolve(__dirname, 'dist/manifest.json')  // 输出文件路径
    })
  ]
}

生成一个 react.dll.js打包文件和一个结构文件manifest.json,manifest.json用于读取打包前文件后打包后文件的对应关系,
可能会有多组文件需要打包。

b.配置打包命令

"script" : {
    "dll": "webpack --config webpack.dll.js --mode=development"
}

c.webpack.config.js中

plugins: [
    // 告诉webpack那些库不参与打包,同时使用时的名称也得变
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, 'dist/manifest.json')
    }),
    // 将某个文件打包输出去,并在html中自动引入该资源
    new AddAssetHtmlPlugin({ 
      filepath: path.resolve(__dirname, 'dist/react.dll.js') 
    })
]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值