“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

In the company, there are usually multiple projects with the same technology stack. After all, it is too tedious to copy common component code among multiple projects, which is not conducive to the maintenance of the component library. Therefore, how to maintain a set of common component code efficiently is very important. In this case, we can generally consider packaging component libraries and publishing them to NPM. Only NPM install XXX is required for each project, avoiding copying from project to project. We are starting to package a common VUE component library using Webpack.

General posture for using the VUE component library in a project

  • 1. Import through import and register the component globally with vue. use method in the import file main.js, then use it directly in any single file component. The following
import Vue from "vue"
import App from "./App.vue"
import mylib from "mylib"
Vue.use(mylib)
new Vue({
  render: h= > h(App)
}).$mount("#app");
Copy the code
  • 2, the above method appears to be once and for all, but as the component library more stronger, I introduced the whole component library code will appear, but I’m in the current project USES only a fraction of a component, but at the time of final project packing wrap up all the component library component code into the bundle files, influence the final code size, This is clearly unreasonable. So we have an on demand way to import component libraries. Here we refer to the ondemand way of importing element-UI, as follows.

Next, if you want to introduce only a few components, such as Button and Select, you need to write the following in main.js:

import Vue from 'vue'; 
import { Button, Select } from 'element-ui'; 
import App from './App.vue'; 
Vue.component(Button.name, Button); 
Vue.component(Select.name, Select);  
new Vue({
    el: '#app'.render: h= > h(App) 
});
Copy the code

Why is it that named imported components can be imported on demand? It was the babel-plugin-Component plug-in that did the conversion for us. Inside the babel-plugin-component, the plugin is added

import { Button, Select } from 'element-ui'; 
Copy the code

Converted to

var button = require('element-ui/lib/button')
var select = require('element-ui/lib/select')
require('element-ui/lib/theme-chalk/button/style.css')
require('element-ui/lib/theme-chalk/select/style.css')
Copy the code

The above element- UI is the name of the component library, and theme-chalk is the name of the folder where the component library style is located, which are configurable. Button, select are component names, and lib is the default directory where the babel-plugin-component plug-in looks for components.

Webpack implements a library of components that can be imported on demand

NPM init creates the project, because each component is packaged separately, so each component exports a function, and then executes this function on vue.use () to complete the global registration of the component. The project directory structure is as follows

components/navbar/navbar.vue
<template>
  <div class="header__all">{{text}}</div>
</template>
<script>
export default {
  name: "navbar".props: {
    text: String}};</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.header__all{
    background-color: # 000000;
    color: #FFFFFF;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 50px;
    width: 100%;
}
</style>
Copy the code
components/navbar/index.js
import navbar from "./navbar.vue";
export default function(Vue) {
    Vue.component(navbar.name,navbar);
}
Copy the code
src/index.js
import navbar from "./components/navbar"
function install(Vue){
  Vue.use(navbar)
}
if(window && window.Vue) {
  Vue.use(install)
}
export default install
Copy the code

The next step is to use WebPack packaging

  • Step 1: Install all required dependencies first
npm i -D webpack webpack-cli babel-loader @babel/core @babel/preset-env babel-plugin-component clean-webpack-plugin css-loader mini-css-extract-plugin node-sass postcss postcss-loader autoprefixer cssnano sass-loader terser-webpack-plugin vue-loader vue-template-compiler
Copy the code
  • Step 2: Configure webpack.config.js
const path = require('path')
const TerserPlugin = require("terser-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
const { VueLoaderPlugin } = require('vue-loader')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode: 'none'.entry: {
    'navbar': './src/components/navbar/index.js'.'navbar.min': './src/components/navbar/index.js'.'test-lib': './src/index.js'.'test-lib.min': './src/index.js'
    
  },
  output: {
    path: path.join(__dirname,"/lib"),
    filename: '[name].js'.libraryTarget: 'umd'.library: '[name]'.libraryExport: 'default'
  },
// externals:[],
  optimization: {
    minimize: true.minimizer: [
        new TerserPlugin({
            test: /\.min\.js$/,})]},module: {
    rules: [{test: /\.vue$/,
        use:  ['vue-loader'] {},test: /\.css$/,
        use:  [MiniCssExtractPlugin.loader,'css-loader'.'postcss-loader'] {},test: /\.s[ac]ss$/i,
          use:  [MiniCssExtractPlugin.loader,'css-loader'.'postcss-loader'.'sass-loader'] {},test: /\.js$/,
        exclude: /node_modules/,
        use:{
            loader: 'babel-loader'.options: {
                cacheDirectory: true}}}]},plugins: [
    new VueLoaderPlugin(),
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
        filename: 'lib-style/[name].css'}})]Copy the code
  • Step 3: Change the main field of package.json and add packaging commands to scripts
"main": "./lib/test-lib.min.js"."scripts": {
    "build": "webpack --config webpack.config.js"
}
Copy the code
  • Step 4: Execute NPM run build to package the component library. After success, the project will have a lib folder to store the code of the packaged component library. Each file in the lib folder has a corresponding. Min file. The.min file is compressed using terser-webpack-plugin and cssnano respectively.

Debug component library

There are two ways to debug a local component library

  1. Create a new test.html file and use the
  2. Vuecli creates a new test project and uses the NPM link to link to the test project

Here is a demonstration of the use of the most brutal way, a new test.html, NPM link you can try it yourself.

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./lib/lib-style/test-lib.min.css">
</head>
<body>
    <div id="app">
        <navbar text="header"></navbar>
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="./lib/test-lib.min.js"></script>
<script>
    new Vue({
        el: '#app'
    })
</script>
</html>
Copy the code

Test results:

At this point, at least, there are no major issues with the code build, but the on-demand functionality has not been accepted, so let’s go ahead and publish the component library to NPM and use it exactly like element-UI in the Vuecli project to see how it works.

NPM release

The steps are very simple, just 4 steps
  1. Register your account and verify your email address on the NPM website.
  2. On the cli, enter NPM login.
  3. If the NPM uses the Taobao mirror source, switch back to the NPM source.
  4. Go to the project directory to publish and perform NPM publish publish.

Once that’s done, NPM Install then installs our own component library in the test project.

Debug component libraries are introduced on demand

In babel.config.js in the test project, add the babel-plugin-component configuration and restart the project. Babel-plugin-component basic configuration reference

// babel.config.js
module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"].plugins: [['component',
      {
        libraryName: 'element-ui'.styleLibraryName: 'theme-chalk'
      },
      'element-ui'
    ],
    [
      'component',
      {
        libraryName: 'test-lib'.styleLibrary: {
          "name": "lib-style".// same with styleLibraryName
          "base": false  // if theme package has a base.css}},'test-lib']]};Copy the code

Use component libraries in test.vue


<template>
<div>
  <navbar :text="msg"></navbar>
  <el-button type="primary" class="dg-margin-t-20">element-button</el-button>
</div>
</template>
<script>
import Vue from "vue";
import { navbar } from "juejintest-lib";
import { button } from "element-ui";
Vue.use(navbar)
Vue.use(button)
export default {
  data:function() {
      return {
          msg: 'text'}}};</script>
<style lang="scss">
.dg-margin-t-20{
    margin-top:20px;
}
</style>

Copy the code

Here we have built the vUE component library to be introduced on demand. In this article, webpack is used as a building tool. In fact, Webpack is usually used to build application projects. For building public libraries, we will use rollup more often.