乐趣区

关于html:Webpack-之常用配置三

作者:余韵之

LazyLoading 懒加载 Chunk 是什么?

咱们能够应用懒加载的形式引入模块,比如说当触发了某个条件,在通过 import 的形式引入模块。这样能够使得我的项目的性能会更加的好。

举个例子

当咱们点击页面的时候,才会去引入 lodash 模块,这里 import()返回的是 promise

async function getComponent() {const {default: _} = await import(/* webpackChunkName:"lodash" */'lodash')
  const element = document.createElement('div')
  element.innerHTML = _.join(['y', 'kk'], '-');
  return element;
}

document.addEventListener('click', () => {getComponent().then(element => {document.body.appendChild(element)
  })
})

同样的路由懒加载的意思,示意当咱们监听到路由变动了,才会去引入对应的页面模块。

因而能够晓得,Chunk 是什么?打包生成几个 JS 文件,就是几个 Chunk

Shimming

Shimming:在打包过程中,有时候须要对代码兼容。这种兼容不局限于浏览器高下版本。

举个例子

每个文件都是一个模块,每个模块都应该引入本人的依赖能力应用该依赖。

import $ from 'jquery'
export function setBackground(){$('body').css('background','red')
}

然而这样的话,每个文件都要写一遍

import $ from 'jquery'

因而能够应用垫片的形式来主动配置

plugins:[
    new webpack.ProvidePlugin({
      $:'jquery',
      _join:['lodash','join']
    })
]

当咱们配置了上述内容,那么意味着当运行代码的时候看到

  • $ 这个符号就会主动去 node_modules 里引入 jquery。他的原理就是主动帮咱们增加了 import 的步骤。
  • 看到_join 就会主动找到 lodash 里 join 的办法

于是咱们能够间接这些一个文件模块应用

export function setBackground(){$('body').css('background', _join(['green'], ''))
}

webpack 与浏览器缓存(caching)

当咱们打包生成了

index.html
main.js
vendors.js

客户端从服务端拿到了两个 js 文件,会保留在浏览器里。客户端刷新后浏览器会先从缓存里获取。
当开发批改了代码,从新打包,生成了上述三个同名文件时,用户刷新后依然是原来的代码并没有更新。
这样如何解决呢?

1、打包文件增加 contentHash

开发环境因为是热更新的,所以本地调试能够不增加,
生产环境在 output 里改为

output: {filename: '[name].[contentHash].js',
    chunkFilename: '[name].[contentHash].js'
}

contentHash 示意只有不扭转源代码的内容,那么 contentHash 所产生的 hash 值是不会变的。如果代码是宰割成不同的 chunk,某个 chunk 没有批改,该 chunk 的文件名 contentHash 也不会批改

同时做了代码宰割的参数最好也配置一下

optimization.splitChunks.cacheGroup.vendors.filename = 'vendors.[contentHash].js'

2、对老版本的兼容

可能老的版本即便不改内容,contentHash 值也会扭转,这个时候能够配置

optimization: {
    runtimeChunk:{name:'runtime'}
}

新版本增加这个 runtimeChunk 也是没有问题的,此时打包会多出一个 runtime.xxxxxxx.js 文件

这是怎么回事呢?

因为在旧的 webpack 版本里 main.js(业务逻辑)和 vendors.js(第三方库)之间是存在关联的,这部分的解决代码放在 mainfest, 尽管没有扭转代码,但在旧版本的 webpack 里 mainfest 包和包之间的关系每次打包可能会变动,当咱们配置了 runtimeChunk 的时候就把 mainfest 这块关系相干的代码抽离进去了放在 runtime.js 里

因而这样就解决了这个兼容老版本的问题。

对 CSS 代码宰割

失常打包的话,会把 CSS 文件一起打包的 main.js 文件,如何进行 CSS 代码宰割呢?

1、应用一个插件:mini-css-extract-plugin

但这个插件有一个毛病,目前不反对热更新,所以适宜线上环境做打包

配置形式装置依赖

yarn add mini-css-extract-plugin

在生产环境 的 webpack.config.js 配置

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

  module:{
    rules:[
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {importLoaders: 2}
          },
          'sass-loader',
          'postcss-loader'
        ]
      }, {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader'
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({filename: "[name].css", //index.html 间接引入的文件
      chunkFilename: "id.css" // 间接援用的文件
    })
  ]

留神 如果此时应用了 tree shaking 看看 package.json 里 sideEffects 配置。如果为 false 那么 css 代码是没有宰割的。须要把 css tree shaking 排除在外。批改如下:

 "sideEffects": ["*.css"],

2、接下来对合并的 CSS 代码压缩

装置依赖

yarn add optimize-css-assets-webpack-plugin -D

生产环境

const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')

optimization:{minimizer:[new OptimizeCSSAssetsPlugin({})]
}

打包剖析

生成 webpack 打包剖析 json

webpack --profile --json > stats.json --config ./build/webpack.dev.js

而后把生成的 stats.json 放入相干的剖析网站就能够看到可视化的数据。当然也能够配置 analyzer

装置依赖

npm install webpack-bundle-analyzer --save-dev

在 webpack.config.js 配置

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
  ...
  configureWebpack: {
    plugins: [
        new BundleAnalyzerPlugin({
                    //  能够是 `server`,`static` 或 `disabled`。//  在 `server` 模式下,分析器将启动 HTTP 服务器来显示软件包报告。//  在“动态”模式下,会生成带有报告的单个 HTML 文件。//  在 `disabled` 模式下,你能够应用这个插件来将 `generateStatsFile` 设置为 `true` 来生成 Webpack Stats JSON 文件。analyzerMode: 'server',
                    //  将在“服务器”模式下应用的主机启动 HTTP 服务器。analyzerHost: '127.0.0.1',
                    //  将在“服务器”模式下应用的端口启动 HTTP 服务器。analyzerPort: 8888, 
                    //  门路捆绑,将在 `static` 模式下生成的报告文件。//  绝对于捆绑输入目录。reportFilename: 'report.html',
                    //  模块大小默认显示在报告中。//  应该是 `stat`,`parsed` 或者 `gzip` 中的一个。//  无关更多信息,请参见“定义”一节。defaultSizes: 'parsed',
                    //  在默认浏览器中主动关上报告
                    openAnalyzer: true,
                    //  如果为 true,则 Webpack Stats JSON 文件将在 bundle 输入目录中生成
                    generateStatsFile: false, 
                    //  如果 `generateStatsFile` 为 `true`,将会生成 Webpack Stats JSON 文件的名字。//  绝对于捆绑输入目录。statsFilename: 'stats.json',
                    //  stats.toJson()办法的选项。//  例如,您能够应用 `source:false` 选项排除统计文件中模块的起源。//  在这里查看更多选项:https://github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
                    statsOptions: null,
                    logLevel: 'info' // 日志级别。能够是 '信息','正告','谬误' 或 '缄默'。})
    ]
  }, 
  ...
};

应用形式 在打包或者启动的时候加 –report

npm run serve --report
npm run build --report

prefetching && preloading

关注代码使用率:一开始不会执行的代码不要加载进去,而是当交互了再去加载。

webpack 心愿尽可能应用异步加载模快在第一次加载进步性能,而同步是第二次加载了减少缓存对性能的晋升是无限的。

document.addEventListener('click', () => {import('./click.js').then(({default:func}) => {func()
  })
})

留神 但这样会存在一个问题,就是当用户点击交互了才下载代码可能会有一点小小的提早,如何解决这个问题?

解决方案就是:prefetching/preloading

  • prefetching 会等到外围先展现的代码加载结束了,等宽带闲暇再持续下载。

只须要在代码增加如下内容即可:

document.addEventListener('click', () => {import(/* webpackPrefetch:true */'./click.js').then(({default:func}) => {func()
  })
})

当用户点击了,依然会下载 click.js 文件,然而应用的工夫会十分短,因为之前曾经下载过了有了缓存了。

  • preloading 会和主的代码同时下载。
document.addEventListener('click', () => {import(/* webpackPreload:true */'./click.js').then(({default:func}) => {func()
  })
})

因而性能优化最好去思考代码的使用率更高。


对 Electron 感兴趣?请关注咱们的开源我的项目 Electron Playground,带你极速上手 Electron。

咱们每周五会精选一些有意思的文章和音讯和大家分享,来掘金关注咱们的 晓前端周刊。


咱们是好将来 · 晓黑板前端技术团队。
咱们会常常与大家分享最新最酷的行业技术常识。
欢送来 知乎、掘金、Segmentfault、CSDN、简书、开源中国、博客园 关注咱们。

退出移动版