写一个babel插件实现loadsh按需打包的功能

285 阅读2分钟

juejin.cn/post/684490…

juejin.cn/post/701774…

背景

背景:当我们同时引入一个包中的两个方法,有两种方式

第一种形式:

import {flatten,join} from 'lodash';

第二种形式:

import flatten from 'lodash/flatten'
import join from 'lodash/join'

第一种方式的引入会把整个loadsh包都引进来,打包后的文件大小为550kb;

第二种方法是只会引入包中的这两个方法,打包后的文件大小为21kb。

显然我们要用第二种

但是一般的项目中,大部分都是以import结构的形式,所以这里我们就写一个插件,当我们写成第一种形式引入的时候,利用插件转化成第二种形式

插件实现

下面是插件的实现:

  1. 新建文件夹babel-plugin-demand-loading
  2. 执行npm init -y
  3. 安装babel-core、babel-types
  4. 根目录下新建index.js,并编写代码,如下:
const babel = require('babel-core')
const types = require('babel-types')

module.exports = {
    visitor: {
    // 这里的ref是ImportDeclaration的第二个参数,这里的值是.babelrc中的 {
    // "library": "lodash" //}, 这里是指定 我们在引用哪个库的时候使用这个插件
        ImportDeclaration(path, ref={}){
           let {opts} = ref
           let node = path.node
           let specifiers = node.specifiers
           if(opts.library === node.source.value && !types.isImportDeclaration(specifiers[0])){
                const newImport = specifiers.map((specifier) => (
                   types.importDeclaration([types.importDefaultSpecifier(specifier.local)], types.stringLiteral(`${node.source.value}/${specifier.local.name}`))
                   ))
                path.replaceWithMultiple(newImport)
           }
        }
    }
}
  1. yalc publish本地发布包
  2. 在项目中使用命令yalc add babel-plugin-demand-loading@1.0.0 -D安装该插件
  3. 在webpack.config.js文件中配置该插件
const PluginDemandLoading = require('babel-plugin-demand-loading')

module : {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|browser_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: [ 
              [PluginDemandLoading,{
              'library': 'lodash', // 指定哪些库使用这个插件
              }]
          ]
          }
        }
      },
    ]
 }

使用该babel插件后,打包后的文件大小为19kb.

import {flatten, join} from 'lodash'

const arr = [1,2,['3','4',6,7]] 
console.log(flatten(arr)) // [ 1, 2, '3', '4', 6, 7 ]
console.log(join(flatten(arr))) //1,2,3,4,6,7

AST Explorer

astexplorer.net/

babel插件注意事项

  • babel插件的文件夹命名,必须以babel-plugin-xxx(你写的插件名)命名,否则引入不成功。
  • babel插件返回的是一个对象,里面有一个访问者模式的visitor对象,里面是我们的转化代码

使用 Babel-plugin-import

使用 Tree-Shaking