Re-encapsulate the Element-UI component based on vuE-CLI4.x and publish to NPM

Reprinted from: www.yuque.com/homacheuk/d…

Other: blog.csdn.net/shidouyu/ar…

  https://juejin.cn/post/6844904000655998984#heading-19
  
  https://juejin.cn/post/6844903926941089806#heading-29
Copy the code

demand

Because of the need to re-create a common set of components based on EL components and available to multiple subsystems, this choice is to encapsulate and publish the components to NPM.

The body of the

There are many ways to encapsulate a component library, but we started simple and created it directly using VUe-CLI, which is a bit redundant but makes it easier to debug components.

Install VUE-CLI4 and create a component library project

// Install scaffolding YARN Global add @vue/cli // Create a project vue create jz-VUe-uiCopy the code
  • After creating the project (if you are not familiar with the process, you can search for it), we have the following project catalog. Vuex, Router, etc., which are required by the basic project, were added because I need them in the later stage of the project. You can decide whether to add them according to your personal needs.

Adjusted for

Take a look at element’s project structure. Rename SRC to Examples and add packages to store our custom components.

However, the cli will start the service under SRC by default. If the directory name is changed, we need to manually modify the configuration. Vue-cli3 provides the file of customized package configuration project, we only need to manually create vue.config.js. The specific modifications are as follows:

1.First modify the entry file address to examples main.js,2.Next, add Packages to the package compilation task3.Change the nickname of the @ pathconst path = require('path') // Introduce the path module
function resolve (dir) {
  return path.join(__dirname, dir) // path.join(__dirname) Sets the absolute path
}
module.exports = {
  publicPath: '/'.// 1. Change the import and export file names
  pages: {
    index: {
      entry: 'examples/main.js'.// Modify the entry
      template: 'public/index.html'.filename: 'index.html'}},// 2. Extend webPack configuration to include Packages in compilation
  chainWebpack: config= > {
    config.resolve.alias
      .set(The '@', resolve('./examples')) //3. Modify the shortcut path
      .set('components', resolve('./examples/components'))
      .set('views', resolve('./examples/views'))
      .set('assets', resolve('./examples/assets'))
    config.module
      .rule('js')
      .include
      .add('/packages/')
      .end()
      .use('babel')
      .loader('babel - loader')
      .tap(options= > {
        // Modify its options...

        return options
      })
  },
  /* Output file directory: the name of the directory that generated the file when NPM run build */
  outputDir: 'jz-vue-ui'./* The directory where generated static resources (mixin, CSS, img, fonts) are placed (relative to outputDir) */
  assetsDir: 'assets'./* Whether to generate the sourceMap file when building the production package, false will speed up the build */
  productionSourceMap: false./* By default, generated static resources include hash in their file names for better cache control. You can turn off file name hashing by setting this option to false. (false is to leave the original file name unchanged) */
  filenameHashing: false./* EsLint checks when code is saved */
  lintOnSave: false./* webpack-dev-server */
  devServer: {
    /* Automatically opens the browser */
    open: true./* If set to 0.0.0.0, all addresses can access */
    host: '192.168.0.142'.port: 8080.https: false.hotOnly: false}}Copy the code

Write el-based components

  • Since we need to package the components based on el, we will install the Element-UI first. We can also click on the Vue UI as described online, but we will use the traditional way
yarn add element-ui -S
Copy the code

However, when writing components, it is relatively space saving to directly use on-demand import, so we will import according to the official website

yarn add babel-plugin-component -D
Copy the code

Add it to babel.config.js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'].plugins: [['component',
      {
        libraryName: 'element-ui'.styleLibraryName: 'theme-chalk'}}]]Copy the code
  • Let’s take a Button component as an example. Here we only implement a simpler component.

    First we create a Button directory in the Packages directory and then SRC to store the component's source codeCopy the code
<template>
  <div>
    <p>Test the q</p>
    <Button>el-button</Button>
  </div>
</template>
<script>
import { Button } from 'element-ui'// Import on demand
export default {
  name: 'jz-button'.components: { Button }
}
</script>
Copy the code

Button index.js to install as a vue component:

import Button from './src/index.vue'

Button.install = function (Vue) {
  Vue.component(Button.name, Button)
}

export default Button
Copy the code

Next we import the component in the packages entry file and install the export.)

It’s important to note here, because since EL has style CSS, and we’re using on-demand import, we’re going to introduce it here

import 'element-ui/lib/theme-chalk/index.css'// Introduce the el style
import Button from './Button/index'
import Input from './Input/index'
// Store a list of components
const components = [Button]
// Define the install method that accepts Vue as an argument. If the plug-in is registered with use, all components will be registered

const install = function (Vue) {
  // Determine whether to install it

  if (install.installed) return
  // Iterate over registered global components
  components.forEach(component= > {
    Vue.component('jz-button', component)
  })
}
// Check whether the file is imported directly

if (typeof window! = ='undefined' && window.Vue) {
  install(window.Vue)
}

export default {// Import all
  // Exported objects must have install to be installed by vue.use ()
  install

}
export {// Local import
  Button,
  Input
}
Copy the code

The test code

If you want to see the effects of your components, you can import the components to the examples directory in main.js, which is essentially a development directory for the project, as follows:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import jzUI from '.. /packages/index'
Vue.config.productionTip = false
Vue.use(jzUI) // Here we introduce all of them directly for convenience
new Vue({
  router,
  store,
  render: h= > h(App)
}).$mount('#app')
Copy the code

Now we can use our component in the project

<template>
  <div id="app">
     <jz-button></jz-button>
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>

<style lang="scss">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983; }}}</style>
Copy the code

Configure the package.json file

As a component library, we have to write our package.json according to NPM’s package distribution rules, which we normally need to configure

Description and keywords of package file are described as follows:

  • Description Specifies the description text of the component library

  • Keywords Keywords of the component library

  • License Agreement

  • Repository Git repository address associated with the repository component

  • Homepage displays the homepage address of the homepage component library

  • The main entry address of the component library (the address introduced when using the component)

  • Private Indicates that the component library is private. If you want to publish the component library to the NPM public network, delete this property or set it to false

  • PublishConfig is used to set the address of the NPM publication. This configuration is critical as an NPM server within the team and can be set up as a private NPM repository

Note: Since we are using unpackaged mode, the direct main entry path is changed to jZ-vue-ui /package, and the incoming path when calling simplifies the call

  // We can use the basic attributes first
  "name": "jz-vue-ui"."version": "0.1.9"."private": false."description": "Jz Front-end Common Component Library"."main": "jz-vue-ui/package".Copy the code

The second is the need to configure the command of packaging, which we will also configure for him first, although we do not use him this time

 "scripts": {
    "serve": "vue-cli-service serve"."build": "vue-cli-service build",json
    "lint": "vue-cli-service lint".// Package name and package entry
    "lib": "vue-cli-service build --target lib --name jz-vue-ui --dest lib packages/index.js"
  },
Copy the code

Finally, we need to create a.npmignore to reduce the size of files that don’t need to be uploaded

# ignore examples/ #packages/ #public/ # ignore the specified file vue.config.js babel.config.js *.mapCopy the code

Published to the NPM

  • This time we will use unpackaged distribution because our component library may also use many third-party libraries and resources to avoid resource loading errors

Packaged and unpackaged releases compare as follows:

  • The method of publishing to NPM is also very simple, first we need to register to the NPM official website to register an account (remember to verify the email), then log in to the console, and finally we execute NPM publish. The specific process is as follows
// login and enter the password as prompted. NPM login // publish the version number needs to be increased each time you publishCopy the code

After release, the effect is as follows:

For use in projects

  • Now let’s create a new VUE project and introduce our component library
// Install the component library yarn add jz-vue-uiCopy the code
  • Since the import path was changed to jZ-vue-ui /package in main configuration, the import here can be directly used jZ-vue-ui
Introduced in main.jsimport Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { Input } from 'jz-vue-ui'
import './css/index.scss' // Overwrite CSS needs to come later
Vue.config.productionTip = false
Vue.use(Input)
new Vue({
  router,
  store,
  render: h= > h(App)
}).$mount('#app')
Copy the code
  • One problem we notice here is that the path introduced is not just the name of our component library. This is because we are publishing without packaging, so we need to manually find the library entry js. The installed component library actually looks like this in node_modules:

  • Let’s use it the same way we used it for debugging
<template>
  <div id="app">
    <jz-input></jz-input>
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>
Copy the code