webpack4从0搭建组件库

lihaixing

一、代码分离

代码分离方法有三种:

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 SplitChunksPlugin 去重和分离 chunk。
  • 动态导入:通过模块中的内联函数调用来分离代码。

二、动态导入(dynamic imports)

  • import()
  • require.ensure

三、预取/预加载模块(prefetch/preload module)

webpack v4.6.0+ 添加了预取和预加载的支持。

在声明 import 时,使用下面这些内置指令,可以让 webpack 输出 "resource hint(资源提示)",来告知浏览器:

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

四、shim预设依赖

(1)shim 预置全局变量

一些 third party(第三方库) 可能会引用一些全局依赖(例如 jQuery 中的 $

以下配置含义:如果你遇到了至少一处用到 _ 变量的模块实例,那请你把lodash package 引入进来,并将其提供给需要用到它的模块。

 // import _ from 'lodash';  // 不需要了, 直接能用_
 
 new webpack.ProvidePlugin({
   _: 'lodash'
 })

也可以只是引用某一个方法join, 通过配置一个“数组路径”(例如 [module, child, ...children?])实现此功能.
这样能更好的和tree shaking配合

new webpack.ProvidePlugin({
//  _: 'lodash'
    join: ['lodash', 'join']
})

(2)细粒度 shim

this=>window
https://v4.webpack.docschina....

(3) 全局 export

如何将没有导出的js代码,通过模块加载

五、渐进式应用网络程序

server-works

六、环境变量

如果设置 env 变量,却没有赋值,--env.production 默认表示将 --env.production 设置为 true
webpack CLI 文档。

webpack --env.NODE_ENV=local --env.production --progress
// 使用env
module.exports = env => {}

七、构建性能要点

(通用环境)==========》

1、webpack更新到最新版本

2、loader(include)

3、引导时间

每个额外的 loader/plugin 都有其启动时间。尽量少使用工具。

4、解析

  • 减少 resolve.modules, resolve.extensions, resolve.mainFiles, resolve.descriptionFiles 中 items 数量,因为他们会增加文件系统调用的次数。
  • 如果你不使用 symlinks(例如 npm link 或者 yarn link),可以设置 resolve.symlinks: false
  • 如果你使用自定义 resolve plugin 规则,并且没有指定 context 上下文,可以设置 resolve.cacheWithContext: false

5、dll

使用 DllPlugin 为更改不频繁的代码生成单独编译结果。这可以提高应用程序的编译速度

6、小即是快(smaller = faster)

  • 使用数量更少/体积更小的 library。
  • 在多页面应用程序中使用 CommonsChunkPlugin
  • 在多页面应用程序中使用 CommonsChunkPlugin,并开启 async 模式。
  • 移除未引用代码。
  • 只编译你当前正在开发的那些代码。

7、worker 池(worker pool)

thread-loader 可以将非常消耗资源的 loader 分流给一个 worker pool。

不要使用太多的 worker,因为 Node.js 的 runtime 和 loader 都有启动开销。最小化 worker 和 main process(主进程) 之间的模块传输。进程间通讯(IPC, inter process communication)是非常消耗资源的。

8、持久化缓存

使用 cache-loader 启用持久化缓存。使用 package.json 中的 "postinstall" 清除缓存目录。

9、自定义 plugin/loader

(开发环境)==========》先不说了

(生产环境)==========》

1、多个 compilation(编译时)

在进行多个 compilation 时,以下工具可以帮助到你:

  • parallel-webpack:它允许在 worker 池中运行 compilation。
  • cache-loader:可以在多个 compilation 之间共享缓存。

2、 source map ===> false

(下列工具存在某些可能会降低构建性能的问题)==========》

1、 babel: 最小化项目中的 preset/plugins 数量。

2、 typescript

  • 在单独的进程中使用 fork-ts-checker-webpack-plugin 进行类型检查。
  • 配置 loader 跳过类型检查。
  • 使用 ts-loader 时,设置 happyPackMode: true / transpileOnly: true

3、 sass

  • node-sass 中有个来自 Node.js 线程池的阻塞线程的 bug。 当使用 thread-loader 时,需要设置 workerParallelJobs: 2

配置项重点详解

(1)mode: "pruduction"

  • 启用 minification(代码压缩) 和 tree shaking (usedExports:true)
  • 自动指定DefinePlugin:process.env.NODE_ENV === 'production'

(2)devtool

source map 简介

  • 生产环境:source-map
  • 开发环境:inline-source-map

(3)optimization

  • splitChunks
splitChunks: {
  chunks: 'all', // 提取公共模块 loadash
  // 将第三方库(library)(例如 lodash 或 react)提取到单独的 vendor chunk 文件中,是比较推荐的做法
  // 利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致。
  cacheGroups: {
    vendor: {
      test: /[\\/]node_modules[\\/]/,
      name: 'vendors',
      chunks: 'all'
    }
  }
},
  • runtimeChunk
runtimeChunk: 'single' // 提取引导模板 将 runtime 代码拆分为一个单独的 chunk

(5)output

// filename: '[name].[contenthash].js', // content hash 内容变化才会变化
filename: 'webpack-numbers.js', 
path: path.resolve(__dirname, 'dist'),

// 暴露 library 这是库名称 import from 'webpackNumbers'
library: 'webpackNumbers', 
libraryTarget: 'umd'

(6)plugins

  • HashedModuleIdsPlugin
const { HashedModuleIdsPlugin } = require('webpack');

plugins: [
    // 不会因模块增加和减少导致的模块内容变化,增加长缓存命中机制
    new HashedModuleIdsPlugin()
],
  • BundleAnalyzerPlugin

分析打包代码

const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');

plugins: [
    new BundleAnalyzerPlugin()
]

(7)externals

// 外部化 lodash
lodash: {
  commonjs: 'lodash',
  commonjs2: 'lodash',
  amd: 'lodash',
  root: '_'
}
// 对于想要实现从一个依赖中调用多个文件的那些 library:
externals: [
    'library/one',
    'library/two',
    // 匹配以 "library/" 开始的所有依赖
    /^library\/.+$/
]

(8)module.rules ( loader )

module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      }
    ]
},
阅读 511

大前端
专注前端开发,分享技术难题,共同进步
31 声望
6 粉丝
0 条评论
你知道吗?

31 声望
6 粉丝
宣传栏