懒加载

动态import使用最多的一个场景就是懒加载(比如路由懒加载)

  • 封装一个component.js,返回一个component对象
  • 我们可以在一个按钮点击时,加载这个对象

如下所示代码,通过import.then的方式加载异步模块

  1. const button = document.createElement('button');
  2. button.innerHTML = '加载元素';
  3. button.addEventListener('click', () => {
  4. import(
  5. /* webpackChunkName:'element' */
  6. /* webpackPreload: true */
  7. './element'
  8. ).then(({ default: element }) => {
  9. document.body.appendChild(element);
  10. });
  11. });
  12. document.body.appendChild(button);

重点是import中的配置

  1. /* webpackPrefetch: true */
  2. /* webpackPreload: true */

这两个都可以做到类似的功能,不过还是有些许不同

  • prefetch(预获取):将来某些导航下可能需要的资源
  • preload(预加载):当前导航下可能需要资源

与 prefetch 指令相比,preload 指令有许多不同之处:

  • preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
  • preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
  • preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
  • 浏览器支持程度不同。

    optimization.runtimeChunk配置

配置runtime相关的代码是否抽取到一个单独的chunk中:

  • runtime相关的代码指的是在运行环境中,对模块进行解析、加载、模块信息相关的代码
  • 比如我们的component、bar两个通过import函数相关的代码加载,就是通过runtime代码完成的
  1. runtimeChunk: {
  2. name: 'runtime-why.js',
  3. },

什么是CDN?

在开发中,我们使用CDN主要是两种方式:

  • 方式一:打包所有的静态资源,放到CDN服务器,用户所有资源都是通过CDN服务器加载的
  • 方式二:一些第三方资源放到CDN服务器上

    使用CDN

配置publicPath

output: {
  filename: '[name].bundle.js',
  path: resolveApp('./build'),
  chunkFilename: '[name].[hash:6].chunk.js',
  publicPath: 'https://jujuul.com.cdn',
},

第三方库的CDN服务器

通常一些出名的开源框架都会将打包后的源码放到一些比较出名的、免费的CDN服务器上:

  • 国际上使用比较多的是unpkg、JSDelivr、cdnjs
  • 国内是bootcdn

如果项目中的第三方库我们不打算由自己的服务器提供,而是使用免费的CDN,那么可以如下配置

// 通过 externals 将我们项目中不打算打包的文件排除
externals: {
  lodash: '_',
  dayjs: 'dayjs',
},
// 然后通过这种方式引入CDN就可以了
<body>
  <div id="app"></div>
  <div id="root"></div>
  <script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
</body>

shimming

shimming是一个概念,是某一类功能的统称:

  • shimming翻译过来我们称之为垫片,相当于给我们的代码填充一些垫片来处理一些问题
  • 比如我们现在依赖一个第三方的库,这个第三方库本身依赖loadash,但是默认没有对lodash进行导入(认为全局存在lodash),那么我们就可以通过 ProvidePlugin 来实现 shimming 的效果
    // 当在代码中遇到某一个变量找不到时,我们会通过ProvidePlugin,自动导入对应的库
    new webpack.ProvidePlugin({
    axios: 'axios',
    get: ['axios', 'get'],
    }),
    
    以上情况是我们的项目中使用了axios,但是我们没有安装axios的依赖,这时可以通过这种方法配置使其获得axios库,我们项目中能使用axios而不报错 ```javascript axios.get(‘https://v2.jinrishici.com/info').then((res) => { console.log(res); });

get(‘https://v2.jinrishici.com/info').then((res) => { console.log(res); });

注意:webpack并不推荐随意的使用 shimming

- webpack背后的整个理念是使前端开发更加模块化
- 也就是说,需要编写具有良好的封闭性的、不存在隐含依赖(比如全局变量)的彼此隔离的模块
<a name="Ghx98"></a>
# MiniCssExtractPlugin

MiniCssExtractPlugin可以帮助我们将css提取到一个独立的css文件中,该插件需要在webpack4+才可以使用
<a name="ul1Tm"></a>
## 安装

` npm i mini-css-extract-plugin -D`
<a name="jz4s8"></a>
## 使用
```javascript
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isProduction = true;
module.exports = {
  mode: 'production',
  plugins: [
    // 生产环境
    new CleanWebpackPlugin({}),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash:8].css',
    }),
  ],
};

在生产环境中webpack.prod.js中引入mini-css-extract-plugin并配置使用

{
  test: /\.css$/,
  use: [
    isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
    'css-loader',
  ],
},

配置loader,根据环境判断使用哪个loader

module.exports = function (env) {
  const isProduction = env.production;
  process.env.production = isProduction;

  const config = isProduction ? prodConfig : devConfig;
  return merge(commonConfig(isProduction), config);
};

获取到当前环境,传入config配置文件,决定是使用webpack.prod.js还是webpack.dev.js

Hash\ContentHash\ChunkHash

在我们给打包的文件进行命名的时候,会使用placeholder,placeholder中有几个属性比较相似:

  • hash、chunkhash、contenthash
  • hash本身是通过MD4的散列函数处理后,生成一个128位的hash值(32个十六进制)