跳到主要内容

babel-plugin-import

一、认识


babel-plugin-import

二、通过 babel-plugin-import 按需引入 lodash


2.1 准备

  1. 安装lodashbabel-loader@babel/corebabel-plugin-import 依赖

    yarn add babel-loader @babel/core babel-plugin-import -D 

    yarn add lodash -S

2.2 常规引入 lodash

  1. webpack.config.js 配置如下 (不使用任何 loader):

    const Path = require('path');

    module.exports = {
    mode: "development",
    entry: Path.resolve(process.cwd(), "./src/index.js"),
    output: {
    filename: "index.js",
    path: Path.resolve(process.cwd(), "./build/"),
    },
    };
  2. 入口文件引入 lodash

    import { flatten, concat } from "lodash";

    console.log(flatten, concat);
  3. 执行webapck build 进行打包编译,编译结果如图所示:

    Preview

    如图所示: 只有两句话而已,但是打包出的文件体积巨大。因为他把真个 lodash 文件都打包了,所以我们需要按需引入,减小打包文件的体积

2.3 按需引入 lodash -- babel.config.js

  1. webpack.config.js 配置 babel-loader 如下:

    {
    test: /\.js$/,
    use: {
    loader: "babel-loader",
    },
    },
  2. webpack.config.js 完整配置如下:

    const Path = require("path");

    module.exports = {
    mode: "development",
    entry: Path.resolve(process.cwd(), "./src/index.js"),
    output: {
    filename: "index.js",
    path: Path.resolve(process.cwd(), "./build/"),
    },
    module: {
    rules: [
    {
    test: /\.js$/,
    use: {
    loader: "babel-loader",
    },
    },
    ],
    },
    };
  3. babel.config.js 配置如下:

    module.exports = {
    plugins: [
    [
    "import",
    {
    libraryName: "lodash",
    libraryDirectory: "",
    },
    ],
    ],
    };
  4. 入口文件引入 lodash

    import { flatten, concat } from "lodash";

    console.log(flatten, concat);
  5. 执行webapck build 进行打包编译,编译结果如图所示:

    Preview

    如图所示: 打包出来的文件体积一下子变得小了许多

2.4 按需引入 lodash -- webpack.config.js

  1. webpack.config.js 配置 babel-loader 如下:

    {
    test: /\.js$/,
    use: {
    loader: 'babel-loader',
    options: {
    plugins: [
    [
    "import", {
    libraryName: "lodash",
    libraryDirectory: "",
    },
    ],
    ],
    },
    },
    }
  2. webpack.config.js 完整代码如下:

    const Path = require('path');

    module.exports = {
    mode: "development",
    entry: Path.resolve(process.cwd(), "./src/index.js"),
    output: {
    filename: "index.js",
    path: Path.resolve(process.cwd(), "./build/"),
    },
    module: {
    rules: [
    {
    test: /\.js$/,
    use: {
    loader: 'babel-loader',
    options: {
    plugins: [
    [
    "import", {
    libraryName: "lodash",
    libraryDirectory: "",
    },
    ],
    ],
    },
    },
    },
    ],
    },
    };
  3. 入口文件引入 lodash

    import { flatten, concat } from "lodash";

    console.log(flatten, concat);
  4. 执行webapck build 进行打包编译,编译结果如图所示:

    Preview

    如图所示: 打包出来的文件体积一下子变得小了许多

三、通过指定路径引入所需 lodash 模块来实现按需引入


  1. webapck.config.js 配置如下(关闭所有 loader):

    const Path = require("path");

    module.exports = {
    mode: "development",
    entry: Path.resolve(process.cwd(), "./src/index.js"),
    output: {
    filename: "index.js",
    path: Path.resolve(process.cwd(), "./build/"),
    },
    module: {
    rules: [
    ],
    },
    };
  2. 入口文件分别指定路径引入所需模块

    // import { flatten, concat } from "lodash";

    import flatten from 'lodash/flatten';
    import concat from 'lodash/concat';

    console.log(flatten, concat);
  3. 执行webapck build 进行打包编译,编译结果如图所示:

    Preview

    如图所示: 打包出来的文件体积跟babel-plugin-import效果是一样的。

四、通过自己实现的 babel-plugin-import 按需引入 lodash


通过指定路径引入所需 lodash 模块来实现按需引入的引入模块方案,我们可以知道所谓的按需引入,就是将import {flatten,concat} from "lodash" 转换为 import flatten from "lodash/flatten"import concat from "lodash/concat"

4.1 不同引入模块方式的 AST 对比

import {flatten,concat} from "lodash" AST 结构:

Preview

import flatten from "lodash/flatten" import concat from "lodash/concat" AST 结构:

Preview

4.2 实现

  1. 根目录/plugins/babel-plugin-import.js 编写插件

    const BabelCore = require("@babel/core");
    const Types = require("babel-types");

    const babelPluginImport = {
    visitor: {
    ImportDeclaration: {
    enter(nodePath, state = { }) {
    const { specifiers, source } = nodePath.node;
    if (
    state.opts.libraryName === "lodash"
    && !Types.isImportDefaultSpecifier(specifiers[0])
    ) {
    const importDeclarations = specifiers.map((specifier) => Types.importDeclaration(
    [Types.importDefaultSpecifier(specifier.local)],
    Types.stringLiteral(`${source.value}/${specifier.local.name}`),
    ));
    nodePath.replaceWithMultiple(importDeclarations);
    }
    },
    },
    },
    };

    module.exports = function () {
    return babelPluginImport;
    };
  2. webpack.config.js 中配置babel-loader,使用自定义插件

    const Path = require("path");

    module.exports = {
    mode: "development",
    devtool: false,
    entry: Path.resolve(process.cwd(), "./src/index.js"),
    output: {
    filename: "index.js",
    path: Path.resolve(process.cwd(), "./build/"),
    },
    module: {
    rules: [
    {
    test: /\.js$/,
    use: {
    loader: "babel-loader",
    options: {
    plugins: [
    [
    Path.resolve(process.cwd(), './plugins/babel-plugin-import.js'),
    {
    libraryName: 'lodash',
    },
    ],
    ],
    },
    },
    },
    ],
    },
    };
  3. 执行webapck build 进行打包编译,编译结果如图所示:

    Preview

    如图所示: 打包出来的文件体积跟babel-plugin-import效果是一样的。