ElementUI源码系列七 - 组件按需引入

2,264 阅读5分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

写在开头

经过前几篇文章的学习,我们现在自己的 ElementUI 项目已经算是初具规模,当然,这还远远不够,不急,路一点一点走,饭一口一口吃。( ̄▽ ̄)

这章我们来讲讲组件的按需引入,前面我们把项目通过 npm pack 打包成本地的 npm 包,在新项目中下载使用时,是用以下方式引入的:

// main.js
import juejinElementUI from 'juejin-element-ui';
import 'juejin-element-ui/lib/theme-chalk/index.css';
Vue.use(juejinElementUI);

这样子会使我们全量的引入整个组件库,我们可以通过控制台的 Sources - webpack:// - . - node_modules - 组件库名称 来看组件库的引入情况。

image.png

按需引入

要实现按需引入的功能,实际也不难,只需要两步,我们需要借助 webpack 的打包功能,把每个组件打包成一个单独的文件;然后在使用的时候利用 babel-plugin-component 插件,帮助我们只引入需要的组件文件即可。

1.把组件打包成单独的文件

接下来,我们先来实现把项目中的组件单独打包。我们在自己的 ElementUI 项目 build 文件夹下新建一个 webpack.components.js 配置文件:

image.png

文件内容和我们 第一篇文章 用的 webpack.common.js 配置文件基本是相似的,下面我们直接来看:

// webpack.components.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const Components = require('../components.json'); // 引入组件的配置文件

const webpackConfig = {
  mode: 'production',
  entry: Components, // {'button': './packages/button/index.js'}
  output: {
    path: path.resolve(process.cwd(), './lib'),
    filename: '[name].js', // 组件名
    libraryTarget: 'commonjs2'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compilerOptions: {
            preserveWhitespace: false
          }
        }
      },
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
};

module.exports = webpackConfig;

上面改动的主要就是 entry 选项,把 entry 选项对应的值替换成了组件的配置文件 components.json 的内容了,实际就是替换成了一个对象,而 webpack 是允许多入口打包,可以接收一个对象的形式。

image.png

还有就是打包后的输出文件,我们改用动态的组件名称来定义文件名,具体可以看这里

写完配置文件,我们来配置一下命令:

"scripts": {
  "dev": "webpack-dev-server --config build/webpack.common.js",
  "build": "webpack --config build/webpack.common.js && webpack --config build/webpack.component.js",
  "build:theme": "gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk",
  "gen": "node build/bin/gen-cssfile.js",
  "new": "node build/bin/new.js",
  "build:entry": "node build/bin/build-entry.js"
},

我们把这个配置文件的命令也加在了 build 命令上,当我们执行 npm run build 命令后,不仅会生成项目打包后的总文件,也会生成按需引入需要的单独组件文件。

直接执行这个命令,会看到项目已经可以生成组件的单独文件了:

image.png

2.通过插件按需引入组件

下面,我们要进入测试组件的按需引入功能了,但在这之前,我们一定要记得把项目重新进行 npm pack 打包,然后重新 npm install 本地放置tgz包的全路径 下载我们项目的包。

然后再下载按需引入需要的插件:npm install babel-plugin-component -D

你需要在测试项目根目录下,新建 .babelrc 文件,文件内容:

{
  "presets": [["@babel/preset-env", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "juejin-element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

这其实 element-ui 官方提供的用法,照着写就行了。

我们把原来的使用方式改改:

// main.js
// import juejinElementUI from 'juejin-element-ui';
// import 'juejin-element-ui/lib/theme-chalk/index.css';
// Vue.use(juejinElementUI);

import {Button} from 'juejin-element-ui';
Vue.use(Button);
// 或写为
// Vue.component(Button.name, Button);

尝试在页面只使用 <el-button></el-button> 标签,观察组件是否使用正常,并且可以看看控制台的引入是否成功按需引入。

image.png

当我们再增加一个组件的使用:

// main.js
import {Button, Divider} from 'juejin-element-ui';
Vue.use(Button);
Vue.use(Divider);

测试代码:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <el-button></el-button>
    <div>
      <span>青春是一个短暂的美梦, 当你醒来时, 它早已消失无踪</span>
      <el-divider></el-divider>
      <span>少量的邪恶足以抵消全部高贵的品质, 害得人声名狼藉</span>
    </div>
    <div>
      <span>头上一片晴天,心中一个想念</span>
      <el-divider content-position="left">少年包青天</el-divider>
      <span>饿了别叫妈, 叫饿了么</span>
      <el-divider></el-divider>
      <span>为了无法计算的价值</span>
      <el-divider content-position="right">阿里云</el-divider>
    </div>
  </div>
</template>

image.png

总结

到这里,我们就完成了组件的按需引入功能了,下面我们稍微来介绍一下这两句代码的背后过程。

import {Button} from 'juejin-element-ui';
Vue.use(Button);
  • import {Button} from 'juejin-element-ui';

    这句代码它主要依赖于项目入口文件 index.js 里面的这些导出,还有 babel-plugin-component 插件与 .babelrc 文件。具体 babel-plugin-component 插件干了些什么就不深究了,但是一定记得,要先有入口文件的导出才有后续的事情,而且使用时,名称要对得上。

    image.png

  • Vue.use(Button); 主要是依赖于每个组件的 index.js 文件,这也是我们在第一篇文件的时候提及过的,不知道你是否还记得。

    image.png




往期内容




至此,本篇文章就写完啦,撒花撒花。

image.png

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。