preface

Most of the tutorials are written in the most direct way, using the Webpack lib mode package, some of the difference may be the use of vue-cli2 /vue-cli3 form, here is a list of simple component library template generation, this tutorial uses vue-cli3 as an example.

The most direct way

Use vue-CLI to create a template (optional) with the generated directory to transform, the changes need to be made as follows:

  1. The original SRC directory is changed to examples for storing sample code. The purpose of the change is to better distinguish functional modules in the name
  2. Create a new Packages directory under the root directory to hold the component library code
  3. Then modify the vue.config.js file (root directory, create one if not)
module.exports = {
    // Change the SRC directory to examples
    pages: {
        index: {
            entry: 'examples/main.js'.template: 'public/index.html'.filename: 'index.html'}},// Extend webpack configuration to include Packages in compilation
    chainWebpack: config= > {
        config.module
            .rule('js')
            .include
                .add('/packages')
                .end()
            .use('babel')
                .loader('babel-loader')
                .tap(options= >options); }}Copy the code
  1. To create a component library file, first create an index.js component library entry under Packages. Export the entire component library
import BaseComp from './packages/BaseComp.vue';

const install = function (Vue) {
    // Globally register components
    Vue.component('BaseComp', BaseComp);
}

export {
    install,
    BaseComp
}

export default {
    install
}
Copy the code
  1. Reform package. Json
    • Adjust packaging scripts, scripts added packaging commands
    • Adjust the main field to point to the packaged lib entry: lib/your-lib-name.umd.min.js
{
    "main": "lib/your-lib-name.umd.min.js"."scripts": {
        "build:lib": "vue-cli-service build --target lib --name your-lib-name --dest lib packages/index.js"}}Copy the code
  1. Publish to NPM (an optional step, or git repository) and import directly to NPM I for business systems

After the above steps, a basic component library template emerges. What do the build:lib parameters mean? To disassembly analysis:

  • vue-cli-service build: Package command, not explained ~
  • --target lib: The build target islibraryfile
  • --name your-lib-nameThe name of the library isyour-lib-name
  • --dest lib: Output directory for compiled library files, specified as lib
  • packages/index.js: Compiler entry

After running the package command, it outputs the packaged file. The compiled file is found in both the UMD module and commonJS module. Here we choose the UMD module as the entrance to the library

STH over and over again

If you don’t have too many requirements on the component library, the direct way of packaging is enough, but as a developer likes to mess around a lot, what does it do? You want the component library to be loaded on demand. In order to achieve this goal, instead of using direct packaging, you need to make the following adjustments:

  • Multi-component entry packaging
  • Export the ES Module

Ok, now that you know the goals above, it’s easy to adjust

Multi-component entry packaging

In the original library project, we exported all the components aggregated together as a package entry, Packages /index.js. Import {SomeComp} from YourComps. Import {SomeComp} from YourComps. Import {SomeComp} from YourComps. Well, you can write that, but the way we packaged it, we exported the entire comp.umd.js file, and Webpack’s Tree shaking can’t remove other components that aren’t introduced. So, local imports are just a convenience of writing, not much practical meaning. To achieve the goal of loading on demand, the project directory structure needs to be transformed as follows

- packages
-- some-comp
--- index.js
--- SomeComp.js
--- index.scss
-- some-comp2
...
Copy the code

Export the ES Module

The previous step is actually preparation for exporting the ES Module. As we know, JavaScript does not have native Module system before ES6, the community has given some solutions, such as AMD/CMD/UMD, ES6 started with JavaScript ES Module, the native Module system uses static compilation, It is possible to see at compile time which modules are actually used and which modules are never used, thanks to static compilation. The target package in vue-CLI only supports umd/common.js, but does not support ES Module. If you let the business system directly reference individual components in the library and leave it to the business system itself to compile, you’re done.

Write conversion script, use Babel to convert once, export to ES Module

/* File path build/build-component.js */
/* Compile component */
const fs = require('fs-extra');
const babel = require('@babel/core');
const path = require('path');

const esDir = path.join(__dirname, '.. /es');
const srcDir = path.join(__dirname, '.. /packages');
const babelConfig = {
    configFile: path.join(__dirname, '.. /babel.config.js')};const scriptRegExp = /\.(js|ts|tsx)$/;
const isScript = path= > scriptRegExp.test(path);

/** * Whether file directory *@param {string} dir 
 */
const isDir = dir= > fs.lstatSync(dir).isDirectory();

/** * compiles the specified directory *@param {string} dir 
 */
function compile(dir) {
    const files = fs.readdirSync(dir);

    files.forEach(file= > {
        const filePath = path.join(dir, file);

        // scan dir
        if (isDir(filePath)) {
            return compile(filePath);
        }

        // compile js or ts
        if (isScript(file)) {
            const { code } = babel.transformFileSync(filePath, babelConfig);
            fs.removeSync(filePath);
            fs.outputFileSync(filePath.replace(scriptRegExp, '.js'), code); }}); }// Clear the directory
fs.emptyDirSync(esDir);
// Compile the directory
fs.copySync(srcDir, esDir)
compile(esDir);
Copy the code

Add a new command to package.json:

"build:es": "node build/build-component.js"
Copy the code

Run build:es to export the ES module successfully

According to the need to introduce

Introduction on demand is aimed at business systems. Currently, there are two popular schemes, namely

  • babel-plugin-import
  • babel-plugin-component

The essence of the two schemes is to shorten the path of the business system to import the library file. Taking babel-plugin-import as an example, the comparison is as follows:

/* do not use babel-plugin-import */
import SomeComp from 'YourComp/es/some-comp/index.js' 

/* use babel-plugin-import */
import { SomeComp } from 'YourComp'
Copy the code

If possible, you must choose the following import form, right? You don’t need to know which directory the component to import is in. To achieve this purpose, you need to configure babel.config.js in the business system as follows

module.exports = { ... .plugins: [['import', {
            libraryName: 'your-lib-name'.libraryDirectory: 'es'
        }, 'your-lib-name']]};Copy the code

Reference from the Vant component library