The rollup configuration packages the VUE component library and publishes it to NPM

In a recent exploration of writing a vUE pull-load pull-refresh component (component library link), the component took weeks to write and was about to be packaged when I encountered a very strange problem; Using vuE-CLI lib package (document here), the result is strange that the package volume is 200K faster, but the component library code should only be 20K, which is unacceptable.

To solve the problem, I went on to look at how vue’s various mobile UI component libraries are built; Vant uses vant/ CLI similar to the VUE-CLI scaffolding tool (if you are interested and take the time to explore how vant/ CLI is built), and other component libraries use WebPack to pack component library packages that are a bit bulky.

In order to optimize the packaging volume, it is not possible to develop a vant/ CLI build tool in a short time. Rollup, Parcel, vite, etc. Rollup was selected because of its high configurability and is particularly suitable for packaging libraries and component libraries. Let’s see how rollup builds and packages a component library for others to use.

Rollup configures the package component library

Rollup is a JavaScript module wrapper that compiles small pieces of code into large, complex pieces of code, such as libraries or applications. In normal application development, we basically choose to use Webpack. In contrast, rollup.js is more used for library packaging, and familiar vue, React, vuex, vuE-Router and so on are all packaged with rollup.

A rollup installation

npm i rollup -g        # global install
npm i rollup -D        # Install the project locally
Copy the code

Rollup configuration file

Rollup packages by writing a configuration file like Webpack:

Create rollup.config.js in the project root directory and specify the entry file and package configuration:

export default {
  input: './src/index.js'.output: [{name: 'libName'.file: './lib/index.js'.format: 'umd'.sourcemap: false.globals: {
        vue: 'vue'}}, {name: 'libName'.file: './lib/index.module.js'.format: 'es'.sourcemap: false.globals: {
        vue: 'vue'}}}],Copy the code

Using the rollup.config.js configuration file, it can be packaged using the rollup –config or rollup -c directives.

It is packaged as umD and ES, and globals specifies which VUE library is used. The packaging files generated by UMD and ES also need to specify the packaged path in the package.json properties:

{
  "main": "lib/index.js"."module": "lib/index.module.js",}Copy the code

After our component library is published to NPM, it can be called using the umD mode or using the ES mode; So how do you identify it in a project? Webpack will also recognize the Module field in package.json from version 2 onwards, and will preferentially use it if it exists. One of the advantages of the ES Module is that code tree shaking, webPack can automatically remove code that is not used in component libraries when packaging.

A rollup plug-in

We have seen the basic usage of rollup, which can only package JS code; In practice, there are many more complex requirements, such as how to support ES6 syntax, how to package vUE files, how to compress our JS code and so on. In rollup, we do this with plug-ins.

The rollup plugin has the functions of both loader and plugin in Webpack. Here are some common plug-ins:

rollup-plugin-vue

Rollup-plugin-vue is used to process Vue files. The version of rollup-plugin-vue used by vue2 and VUe3 projects is different, and the compiler of Vue is different.

  • Vue2: rollup-plugin-vue^5.1.9 + vue-template-compiler
  • Vue3: rollup-plugin-vue^6.0.0 + @vue/ compiler-sFC

Take VUe2 as an example:

NPM I [email protected] VUe-template-compiler --DCopy the code

Add rollup-plugin-vue to rollup.config.js

import vue from 'rollup-plugin-vue'
export default{...plugins:[
    vue()
  ]
}
Copy the code

This allows you to compile and package.vue files.

rollup-plugin-node-resolve

Automatic file identification suffixes:

import resolve from 'rollup-plugin-node-resolve';
export default{...plugins:[
    resolve({
      extensions: ['.vue'.'.js']})]}Copy the code

rollup-plugin-postcss

The plugin needed to handle CSS is rollup-plugin-postcss. It supports CSS file loading, CSS prefixes, CSS compression, SCSS/LESS support, and more.

Here the installation does not do too much emphasis, which packages in the packaging will be automatically prompted.

import postcss from 'rollup-plugin-postcss';
export default{...plugins:[
    postcss({
      plugins: [require('autoprefixer')].// Insert CSS into style
      inject: true.// Put CSS in the same directory as JS
      // extract: true,
      minimize: true.sourceMap: false.extensions: ['.sass'.'.scss'.'.less'.'.css']})]}Copy the code

I use SASS in the component library. I don’t need to install any other SASS package, just use a PostCSS. In my opinion, this is one of the most useful packages, which can pack CSS inline to JS, and can pack CSS separately into a CSS file.

rollup-plugin-babel

Rollup-plugin-babel is used to convert ES6 to ES5 syntax, and other packages such as @babel/preset-env are needed for parsing.

import babel from 'rollup-plugin-babel';
export default{...plugins:[
    babel({
      exclude: 'node_modules/**'.extensions: ['.js'.'.vue']})]}Copy the code

Use @babel/preset-env, @babel/core:

To build Babel. Config. Js:

module.exports = {
  "presets": [["@babel/preset-env"]]}Copy the code

@babel/preset-env can be used to convert many ES6 grammars, and other plug-ins are needed to convert other ES6 grammars.

rollup-plugin-terser

Rollup-plugin-terser is used to compress code, which can be obfuscated and greatly compressed code volume.

import { terser } from 'rollup-plugin-terser';
export default{...plugins:[
    terser(),
  ]
}
Copy the code

Configure packaging commands in package.json:

"scripts": {
  "build": "rollup -c"
},
Copy the code

/ SRC /index.js to generate lib/index.module.js and lib/index.module.js.

The full configuration file is here

About Eslint

Eslint is essential to a component library. In vue-CLI, ESLint is already configured; So how do you add ESLint to rollup configurations?

Install ESLint first:

npm install eslint --D
Copy the code

/node_modules/.bin/eslint –init or NPX eslint –init, follow the instructions to generate the required ESLint configuration scheme, and finally generate an ESLint configuration file.eslintc.js.

Of course the above configuration adds a simple extends: ESLint :recommended is often introduced as a JS checking specification for projects. In the actual project, when configuring rules, there are also VUE rules, it is impossible for the team to discuss the configuration one by one, it takes too much energy. The usual approach is to use coding specifications that are commonly used and followed in the industry. Our component library configuration uses the same ESLint configuration as in VUe-CLI, just copy it.

Finally, configure an eslint validation command:

"scripts": {
  "lint": "eslint ./packages --ext .vue,.js,.ts"."lint-fix": "eslint --fix ./packages --ext .vue,.js,.ts",}Copy the code

NPM run Lint can perform ESLint validation on specified files. NPM run Lint-fix can directly optimize code that esLint fails.

The complete ESLint configuration file is here

About Unit Testing

Component libraries should ensure the stability of functions and code quality, and subsequent open source libraries may have many maintenance problems. It is necessary to ensure the robustness of the program and ensure that the original logic is not damaged in each iteration, so unit testing is particularly important. There are two common frameworks for unit testing in component libraries:

  • Karma + Mocha
  • Jest

Karma can simulate opening a browser automation test, can run style tests in different browsers, etc. Macha provides a framework for automated testing for unit test assertions.

Jest integrates Mocha + JsDOM (Node environment simulates DOM environment, cannot test style) own test coverage, the advantage is zero configuration, contains all the content of the test framework, but also with snapshots and other functions, out of the box.

About Continuous Integration

Continuous integration is about handing over code testing, packaging, and publishing to tools to automate. This is more efficient, and developers only need to worry about developing and committing code to Git.

Github Actions is a great continuous integration tool for publishing, continuous unit testing, and more.

GitHub Actions tutorial

Published to the NPM

If we write a component library in the business and want to share it with others, we will release it to the official repository as NPM package. When we need to use it, we can use NPM install XXX to install it.

So how do you distribute an NPM package?

First, specify the required fields in package.json:

{
  "name": "your package name"."version": "1.0.0"."description": ""."main": "index.js"."keywords": []."author": ""."license": "MIT"
}
Copy the code

Where name writes the package name, you must specify an initial version, version, and then the main entry file, which is essential.

“Main” is the file referenced when someone else imports or requires it, so main is specified as the path of the rollup package.

Once all the component library work is ready, it can be published to NPM using the following NPM command.

npm addUser If you don't have an account, create one
npm login   If you already have an account, log in directly
npm publish Publish component libraries to NPM
Copy the code

subsequent

The architecture of the whole component library is still not perfect, and there is still a lot of work to be done in the future. For example, it is necessary to add unit tests, component library function updates, support vue3, TS, etc., these will be made up in the future when there is time, interested can pay attention to my pull-up load pull-down refresh component library. Don’t worry, let the bullet fly for a while…

Pull-up load pull-down refreshed component libraries

Reference materials (Tanks) :

Rollup goes from getting started to packaging an on-demand component library

Configuration ESLint

How to write elegant and meaningful readme.md