Foreword
The reason to write this article is to build your own course record a component library, but also to those students who want to write a tutorial component library. Component library also wrote some time, also set up the basic shelf almost the same, but look at your build process is not perfect, so come back again organize their own ideas, so that their technology has outputs.
Look under the effect ninecat-ui.github.io
Component library source code ninecat-ui (If you feel good, you can give a start oh)
Here is what I write in this UI component library some Todolsit, has completed the function has been ticked, and if you are interested and I can function together to complete unfinished.
- Custom document directory structure
- By MD component demo to show
- Integrated Travis CI
- Integrated Unit Testing
- Integrated codecov
- Automatically build component document
- According tag automatically publish npm
- Integrated docsearch
- Integrated codepen
- Custom color themes
- Multi-language internationalization
- JavaScript and typescript mixed-use development
Well, let's get started!
Find the right component library prototype
Before you start writing component library, you need to have a good prototype drawing. The more popular domestic and Ant Design Element UI has a corresponding component library, if you want to practice hand, it can be directly used to use.
Here are two links to go download the corresponding UI component library resources.
https://element.eleme.cn/2.0/#/zh-CN/resource
https://ant.design/docs/spec/download-cn
I use Rsuite UI component library, I feel pretty good conscience team.
With a prototype you can start work again!
Initialize the project
Since it is starting from scratch to build a library of components that certainly can not be used to build the scaffolding, it is not called from scratch, and we direct all npm init
start the project.
mkdir ninecat-ui
cd ninecat-ui
npm init
Here is initialized to the project a success, and look below to install the necessary dependencies.
Installation depends
Based on my experience installing its dependencies, the dependent is divided into these types: Core dependence, build dependencies, tool-dependent. Of course, this is according to my functionality to distinguish, and classify more professional look https://zhuanlan.zhihu.com/p/29855253
Here we use the yarn to install dependencies. Now install dependencies to not distinguish what type depend directly yarn add
on the line, and so build a good rack back again distinction belongs to the kind of dependency, and then reconstruct it package.json files on package.json more detailed documentation may refer to https: // docs.npmjs.com/files/package.json
A basic VUE project needs about these dependencies:
VUE, WebPACK, WebPACK-cli, WebPACK-dev-Server, @ babel / Core, babel-Loader, CSS-Loader, HTML-WebPACK-plugin, VUE-Loader
, VUE-Template -compiler
Write the simplest code
Dependence installed, we have to define what the project html template, import documents and VUE home page document root directory of the new index.html, new src directory, create a index.js the src and index.vue.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ninecat-ui</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
index.vue
<template>
<div>Hello Ninecat-ui</div>
</template>
<script>
export default {
name:'App'
}
</script>
index.js
import Vue from 'vue'
import App from './index.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
Well content, now need to look at webpack simple configuration so that the project up and running.
Add the simplest configuration webpack
Create a build directory with the directory, add a configuration file which webpackwebpack.config.base.js
'use strict'
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, '../src/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: "index.js"
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
}),
new VueLoaderPlugin(),
]
}
If some students still do not understand these basic configuration, you should look through what the official documents webpack, oh, given the link: https://www.webpackjs.com/
Be configured as described above, a basic VUE project is built almost, then we need to configure the startup script of the project. Package.json follows in which scripts:
"scripts": {
"start": "webpack-dev-server --config build/webpack.config.base.js"
},
Finally, look at our project directory structure:
Then we run the project:yarn start
OK, here's a basic vue build a good project, we can begin to build behind the components.
The preparation of the first component
First at the root of a new packages
file, and then create a hello in the following folder, open a writing component. Components role is simply that of a simple greeting assembly, passing the name can be displayed Hello, xxx page.
Here we take a look at the directory structure:
Now I need to write about our Hello component.
packages/hello/src/index.vue
<template>
<div>
<h2>Hello, {{name}} !</h2>
</div>
</template>
<script>
export default {
name:'Hello',
props:{
name:{
type:String,
default:'Ninecat UI'
}
}
}
</script>
packages/hello/index.js
import Hello from './src/index.vue'
// install 是默认的方法,供按需引入。
// 当外界在 use 这个组件的时候,就会调用本身的 install 方法,同时传一个 Vue 这个类的参数。
Hello.install = function(Vue){
Vue.component(Hello.name, Hello)
}
export default Hello
Components folder reason for such a write is to allow the components to have a unified export, src directory folder under each component can be extended to other functional components.
src/index.vue
<template>
<div>
<Hello
:name="name"
/>
</div>
</template>
<script>
import Hello from '../packages/hello'
export default {
name:'App',
components:{
Hello
},
data:function(){
return {
name:'Terence'
}
}
}
</script>
OK, here we count encapsulates a simple Hello components, but now we have not achieved after the components packaged with npm install this component library, and then reference inside Hello components, so the following is required to export the configuration and package configuration.
Configuration export and packaging
Well written component requires a unified export, is now a component, will be behind many components, so we need to harmonize the export component.
packages/index.js
import Hello from './hello'
const components = {
Hello
}
const install = function (Vue) {
Object.values(components).forEach(component => {
Vue.component(component.name, component);
})
}
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
install,
Hello
}
Configuration package
build / webpack.config.build.js
'use strict'
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
mode: 'production',
entry: {
'ninecatui': './packages/index.js' // 入口文件
},
output: {
path: path.resolve(__dirname, '../package'), // 出口目录
publicPath: '/package/',
library: 'ninecatui', // 包名
libraryTarget: 'umd',
umdNamedDefine: true // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
},
externals: {
vue: {
root: 'Vue',
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue'
}
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin(),
]
}
Here's the basic package it, test it locally.
In package.json
adding a packaging script,
"build": "webpack --config build/webpack.config.build.js"
We look to build the project:npm run build
Will play a package folder, we cite the component library.
Modify src / index.js
import Vue from 'vue'
import App from './index.vue'
import Ninecatui from '../package/ninecatui'
Vue.use(Ninecatui)
new Vue({
render: h => h(App)
}).$mount('#app')
Modify src / index.vue
<template>
<div>
<Hello
:name="name"
/>
</div>
</template>
<script>
export default {
name:'App',
data:function(){
return {
name:'Ninecat UI'
}
}
}
</script>
Like accessible.
Next we will try to package npm, and then installed locally to refer to the component library.
NPM release
Local packaged test
Modify an entry file package.json file
"main": "package/ninecatui.js",
Then npm pack
you can play a ninecatui-1.0.0.tgz
file.
This file can be installed via npm, in order to test, we can test it directly on the current project.
Before mounting npm need to change the look package.json
of the name, or will conflict at the time of installation, we will
"name": "ninecatui"
Change
"name":"ninecatui-test"
Direct yarn add ./ninecatui-1.0.0.tgz
ornpm install ./ninecatui-1.0.0.tgz
The reason for the increase ./
is because the local path for the installation is a parameter.
If the above effect, congrats on your local installation was successful, let's change it references, to see whether the application can be used normally.
modifysrc/index.js
import Vue from 'vue'
import App from './index.vue'
// 修改引用
import Ninecatui from 'ninecatui'
Vue.use(Ninecatui)
new Vue({
render: h => h(App)
}).$mount('#app')
Nice, normal use, instructions are packaged locally normal use. Let's publish it to npm.
Publish to npm
In the first npm register an account on the official website.
Under the project root directory, login npm account, enter your user name, password, email.
npm login
As information appears to show that you log on success.
Then execute npm publish
to
The figure, ninecatui-test
is our package.
Verification Test npm package
We vue-cli create a vue project, and then install introduced by npm.
direct
vue create hello-world
then
yarn add ninecatui-test
Direct tinkering src/main.js
andsrc/App.vue
src/main.js
import Vue from 'vue'
import App from './App.vue'
import Ninecatui from 'ninecatui-test'
Vue.use(Ninecatui)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
src/App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<Hello
:name="name"
/>
</div>
</template>
<script>
export default {
name: 'App',
data:function(){
return {
name:'Ninecat UI'
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Congratulations, first npm package successfully published. npm publish successfully taken the least a small step back but also continue to optimize the project engineering.