I have been using Element UI for a long time, and I have to say that the Ele. me team is really good. People are always curious, wondering when they will try to build their own component library, just when the team needed a simple component library, so they made some attempts. Was embarrassed to take out, think of yourself is nothing more than the others write something ten thousand times, and I wrote the ten thousand and first times, later friends advised me to say, sometimes and not others look good in what you do, just want to see you have any experience in this field, think later, said the case, then their own theres something share with you.

preface

I used the WebPack template when initializing the project using the Vue CLI, and packaging is an important issue when developing component libraries to accommodate on-demand loading and development previews. The problem of development preview is relatively easy to solve, which can be solved by modifying the configuration of entry in the original WebPack development environment. Loading on demand is more troublesome, and each developed component needs to be packaged separately. My idea is to configure WebPack with multiple entry and multiple exit. What remains is the specific problems encountered in developing components and packaging the entire component library for full introduction, which will be shared below.

Basic configuration

Initialization project:

# 2. X version
# Global install vUE - CLI tool
npm install -g vue-cli
Initialize the project
vue init webpack MyComponent
Copy the code

Previously, I had been using vue-CLI (2.x) and now it is 3.x. The initialization project will be a little different from 2.x.

# 3. X version
# Global install vUE - CLI tool
npm install -g @vue/cli
npm install -g @vue/cli-init
Initialize the project
vue init webpack MyComponent
Copy the code

For development preview, I changed SRC to example to write the development sample to test the components, and then created a new SRC folder with the modified directory structure:

If you want to modify webpack.base.conf.js in the build folder, you just need to modify the entry in the WebPack configuration. The information in this file exists as the default configuration of the webPack package.

module.exports = {
  context: path.resolve(__dirname, '.. / '),
  entry: {
    app: './src/main.js'
  }
  // ...
}

/ / modified
module.exports = {
  context: path.resolve(__dirname, '.. / '),
  entry: {
    app: './example/main.js'
  }
  // ...
}
Copy the code

To get a preview, run the NPM run dev command and see the classic Welcome to Your vue.js App.

The development of component

Create index.js in the new SRC folder, which will be used later in the full import. Then create a components folder to hold all the components.

The index.js in my-button is for later loading on demand.

The main content of the vue:

<! --main.vue--> <template> <button class="my-button" :class="['my-button-size-'+size]" @click="handleClick"> <slot></slot>  </button> </template> <script> export default { name: 'MyButton', props: Size: {type: String, default: 'big'}}, methods: {/** * handleClick () {this.$emit('click')}} </script> <style scoped> /* Initialization */. My-button {display: inline-block; line-height: 1; cursor: pointer; background: #fff; border: 1px solid #ddd; color: #000; text-align: center; outline: none; font-size: 14px; border-radius: 4px; } /* Button big style */.my-button.my-button-size-big {padding: 12px 20px; } /* Button mid style */.my-button. my-button-side-mid {padding: 10px 20px; } /* Button small style */.my-button.my-button-size-small {padding: 10px 10px; } </style>Copy the code

The contents of the index.js file in my-button can be omitted if the component library only needs to be fully imported, and some modifications will be made to the file later:

'use strict'
// index.js in my-button
import main from './src/main'

export default main
Copy the code

Index.js in SRC:

'use strict'
// index.js in SRC
import MyButton from './components/my-button'

const components = [
  MyButton
]

Plugins in vue.js should expose an install method. The first argument to this method is the Vue constructor, and the second argument is an optional option object
const install = function (Vue) {
  components.forEach(component= > {
    Vue.component: Register or get global components
    Vue.component(component.name, component)
  })
}

// When using vue. use to install the plug-in globally, the install method must be provided, where export default is used for vue. use
export default {
  install
}
Copy the code

Then change the file in the example folder to preview the effect.

The main changes are importing components, adding routing information, and writing the demo of components.

Add two lines of code to main.js to globally introduce the developed component:

// ...
// Import the developed component library,
import MyComponent from '.. /src'

// Install the developed component library using vue. use
Vue.use(MyComponent)
// ...
Copy the code

This gives you the freedom to use MyButton in Example.

<template> <div class="example "> <my-button @click="clickFunc"> this is a button </my-button> <my-button size="mid" </my-button> <my-button size="small" @click="clickFunc"> </my-button> </template> <script> export default { name: 'example-button', methods: { clickFunc () { alert('Click') } } } </script> <style scoped> </style>Copy the code

Effect preview:

This is a very simple component, many places do not do, such as: button hover effect, active effect… It’s still a long way from being a full-fledged component, but the general idea is that you can add other things later as needed.

Webpack is packaged for full import

The result is a component library with only one component. Package the component library in a new directory dist.

Start with a connection: Webpack packs the JavaScript Library

The configuration of Webpack is quite complicated. My general idea is to change the original entry to index.js in SRC and modify the necessary configuration according to the specification of Webpack packaging Library.

Use webpack.publish.conf.js to package component libraries in the build folder:

// ...
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')

baseWebpackConfig.entry = {}

const webpackConfig = merge(baseWebpackConfig, {
  // ...
  devtool: config.publish.productionSourceMap ? '#source-map' : false.entry: {
    myComponent: './src/index.js'
  },
  output: {
    path: config.publish.distRoot + '/dist'.filename: 'index.js'.publicPath: config.publish.assetsPublicPath,
    library: 'my-component'.libraryTarget: 'umd'.umdNamedDefine: true
  },
  externals: {
    vue: {
      root: 'Vue'.commonjs: 'vue'.commonjs2: 'vue'.amd: 'vue'}},// ...
})

// ...
Copy the code

The purpose of each configuration can be found on the Webpack website, without further ado, with the link: Webpack Configuration

The most overlooked is that in the build folder, utils.js will generate different paths for each Webpack loader depending on the process.env.node_env environment variable.

Finally modify package.json:

{/ /... "private": false, "main": "dist/index.js", "scripts": { // ... "build:my-component": "node build/publish.js" // ... }}Copy the code

Masking a very small component library is complete, so far only the fully imported parts are written, and the imported parts will be added later.

Finally, I posted the github address: MyComponent. For details, you can see the source code. Since the component library I made before is not my own work, it also contains the work of my design colleagues

Far from a mature component library is very, very far, but there is such an experience to see others mature component library source code will be more familiar, I hope to help you ~