rollup+vue3 develop personal component library

rollup+vue3 develop personal component library

First of all, we need to know what rollup does

What does rollup do?

rollup is a JavaScript packaging module tool that can compile small codes into large blocks of complex codes, such as libraries or applications. Rollup uses new standardized formats for code modules. These standards are included in the ES6 version of JavaScript instead of the previous special solutions such as CommonJS and AMD. ES6 modules allow you to freely and seamlessly use the most useful independent functions in your favorite library, and your project does not have to carry other unused code. The ES6 module will ultimately be implemented natively by the browser, but currently Rollup can make you experience it in advance.

Reference documents:
rollup Chinese document
rollup plug-in collection

Install rollup

  1. Preferred installation
    node.js
  2. Use the following command to install globally
ROLLUP the install NPM - Global //I ROLLUP -g NPM or duplicated code
  1. To check whether the installation is successful, you only need to type in the terminal: rollup

The above indicates the global

rollup
Successful installation

Realize a simple hello world

  1. Create a folder, create under the folder
    index.js
    ,
    hello.js

The hello.js code is as follows:

export function hello () { Return 'Hello' } export function world () { Return 'World' } Copy code

The index.js code is as follows:

Import {Hello, World} from './hello.js' const Result = Hello () + World () to copy the code
  1. To compile, enter the following command in the terminal:
npx rollup index.js --file dist/bundle.js --format iife duplicated code

We found that a dist folder was packaged as follows:

Next we look at the contents of the package:

At this time we will be very confused. Say hello, what about the world? In fact, this is because of the role of tree-shaking, does it feel similar to webpack? Then we are doing some deformation:

Import {Hello, World} from './hello.js' const Result = Hello () + World () Document .getElementById ( 'App' ) = Result .innerHTML duplicated code

Then pack and see the output code

At this time, there is hello and world. By comparison, it is found that the packaged code of rollup is clearer than that of webpack. Next, we will discuss the difference between webpack and rollup.

webpack and rollup

webpack

The construction of large-scale SPA projects is what we often call web applications.

  • Process various resource files through various Loaders
  • Some processing of the overall file through various plug-ins Plugins
  • code spliting extracts public modules
  • Provide a webpack-dev-server for local development
  • Support HMR module for hot replacement

rollup

  • At the beginning of rollup design, a class library with flat structure and outstanding performance was built for ES module.
  • The purpose is to package the ES module to generate a specific JS module file and reduce its size
  • The compiled code is more readable, smaller in content, and more efficient in execution
  • Simpler configuration

By the way, let's talk about ES module rules

  • The import statement can only appear as the top level of the module, and cannot appear in the function if, which is different from commonJS.
  • The module name of ES module can only be a string constant
  • No matter where the import statement position appears, all imports must be completed when the module is initialized

webpack VS rollup

Through the above, we can know that webpack is suitable when building App applications, and it is more suitable to build class library rollup.

Let's try to configure rolluop next

rolluop configuration

  1. Create a new folder
    rolluplearn
    Execute under the directory
    npm init -y
  2. Install rollup
  3. Create the following directory structure and create a new file
    rollup.config.js

3. Write the rollup configuration as follows:

//read the json file import json from '@rollup/plugin-json' ; export default { input : 'main.js' , input : 'main.js' , //entry file output : { file : 'dist/bundle .js' , //Package file address format : 'esm' , //Package format is esmodule } plugins : [json()] } Copy code
  1. in
    package.json
    Edit the packaging script in:
"scripts" : { "build" : "rollup --config rollup.config.js" } Copy code
  1. Start writing main.j and src/test.js files

src/test.js

const hell = ()=> { console .log( 'hell' ) } const fn = () => { console .log( 'fn' ) } export { hell, fn } Copy code

main.js

import {fn, hell} from './src/test' import {version} from './package.json' console .log(version) fn() Copy code
  1. carried out
    npm run build
    , The results are as follows:

Rollup is relatively simple and not as complicated as the configuration of weebpack. Next, we will introduce the development of plugins for vue3.

Vue3 plug-in system development

Add global functions to vue3 applications, generally Object has one

install
Method or direct use
function
, They are not strictly restricted, and generally have the following functions:

  • Add global methods and properties
  • Add global resources and instructions
  • Add some component options through global mixin
  • Add the instance method of app through config.globalProperties

Develop a plug-in

Global approach

Use vue-cli to create a project, in

components
Create under
test.plugin.ts
The file, the code is as follows:

Import {} the App from 'VUE' const plugins = { the install ( App: the App ) { app.config.globalProperties.$echo = ()=> { console .log( 'echo plugin' ) } } } export default plugins Copy code

Next in

main.ts
Global use

import testPlugin from './components/test.plugin' createApp(App) .use(store) .use(router) .use(testPlugin) .mount ( '#app' ) copying the code

At this point we have successfully registered a global method

$echo
, And then we call to try to see if it succeeds, in
App.vue
Write the following code:

<Script lang = "TS" > Import {defineComponent, getCurrentInstance} from 'VUE' Export default defineComponent ({ Setup () { //getCurrentInstance returns the instance object of the current component getCurrentInstance()?.appContext.config.globalProperties.$echo() } }) </script> Copy code

View browser console

It shows that our global method has been added successfully, let's take a look at how to add global components.

Global components

Still in

mian.ts
Make some changes in

Import {} the App from 'VUE' const plugins = { the install ( App: the App ) { app.config.globalProperties.$echo = ()=> { console .log( 'echo plugin' ) } app.component(HelloWord.name, HelloWord) } } Export default plugins copy the code

In the use of global methods, we have been

main.ts
Used in
use
The method is registered globally, then we only need to use it in App.vue, as follows:

<template> < div id = "nav" > < HelloWorld msg = "Welcome to Your Vue.js + TypeScript App"/> < router-link to = "/" > Home </router-link > | < router-link to = "/about" > About </router-link > </div > < router-view/> </template> Copy code

Check the browser and find that the global component has been registered successfully

Overall, it is actually similar to vue2, the main difference is:

  • The global method of vue2 is mounted on the prototype object of vue, and vue3 is mounted on
    app.config.globalProperties
    Method
  • When calling, vue2 can directly use this.xxx to call, vue3 needs
    getCurrentInstance()?.appContext.config.globalProperties
    Make a call

At this point, the development of a plug-in using vue3 is basically complete. Next, we need to understand how a component library entry should be developed.

Component library entry file design

When we use a component library, there are generally two ways to import it, one is global import and the other is on-demand loading. So there should be such an index.ts file when exporting:

import componentA from './a' const componentList = [ componentA ] const install = (app: App) { ... } //Export a single expoert { ... } //Export all export default { install } Copy code

in

componentA
There should also be one
install
Method, how should it be implemented? Make some modifications to the project downloaded from the original vue-cli, the directory is as follows:

Now it is mainly realized

components/TText/index.ts
with
index.ts
components/TText/index.ts

Import {} the App from 'VUE' //just written a line assembly Import TText from './TText.vue' //Add the install method to the component to facilitate the direct use of a single component TText.install = ( app: App )=> { app.component(TText.name, TText) } Export default TText copy the code

index.ts

Import {} the App from 'VUE' Import TText from './components/TText' //list of components const Components = [ TText ] //Use all components const install = ( app: App )=> { components.forEach( component => { app.component(component.name, component) }) } export { TText, install } Export default {} the install copy the code

At this point, we have completed the development of the component entry file. The other basics are to directly build the wheel according to this model. Next, we will use rollup to package into umd and esmodule format files.

Add tollup configuration and package

Root directory creation

build
Folder and create accordingly

  1. rollup.config.js
    : Common basic configuration
  2. rollup.esm.config.js
    : Package esmodule file configuration
  3. rollup.umd.config.js
    Package umd file configuration

Because they are all configurations, they are written directly, you can see the following remarks

//vue file processing plug- Import vue from 'ROLLUP-plugin-vue' //css file processing plug- Import css from 'ROLLUP-plugin-css-only' //ts processing plug-ins Import the typescript from 'ROLLUP-plugin-typescript2' //Used to use third-party modules in the node unit module import {nodeResolve} from '@rollup/plugin-node-resolve' import {name} from '../package.json' //Output the packaged file name type 1 .esm 2.umd const file = type => `dist/${name} . ${type} .js` const overrides = { compilerOptions: { ]declaration : true }, //Generate .d.ts files exclude : [ "tests/**/*.ts" , "tests/**/*.tsx" } export {name, file} export default { input : 'src/index.ts' , output : { name, file : file( 'esm' ), format : 'es' }, plugins : [ nodeResolve(), typescript({ tsconfigOverride : overrides }), vue(), css({ output : 'bundle.css' }) //You can modify the output file name by yourself ], external : [ 'vue' , 'lodash-es' ] //specify which modules are externally referenced } Copy code

rollup.esm.config.js

import basicConfig, {file, name} from './rollup.config' export default { ...basicConfig, output : { name, file : file( 'esm' ), format : 'es' } } Copy code

rollup.umd.config.js

import basicConfig, {name, file} from './rollup.config' export default { ...basicConfig, output : { name : 'thComponents' , file : file( 'umd' ), format : 'umd' , globals : { //Set the name of the global variable'vue ' : 'Vue' , 'lodash-es' : ' _' }, exports : 'named' } } Copy code

Write packaging script

"scripts" : { "build" : "npm run clean && npm run build:esm && npm run build:umd" , //The overall packaging instruction "build:esm" : "rollup --config ./build/rollup.esm .config.js" , //package esmodule "build:umd" : "rollup --config ./build/rollup.umd.config.js" , //package umd format "clean" : "rimraf ./dist" //Clear dist }, Copy code

run

npm run build

View Results

The components have been packaged, and then we will use npm link to test locally

Publish components

Use npm link for component library testing

  1. Configure package.json
{ "name" : "th-bricks" , "version" : "0.1.0" , "private" : false , "author" : "linlei" , "main" : "dist/th-bricks.umd.js" , "module" : "dist/th-bricks.esm.js" , "types" : "dist/index.d.ts" ... } Copy code
  1. Execute in the root directory:
    npm link

3. Use in the project

  • Configuration
"dependencies" : { ... "th-bricks" : "0.1.0" } Copy code
  1. carried out
    npm link th-bricks

  1. Introduced in the main.ts of the project and used in App.vue

main.ts

Import {createApp} from 'VUE' Import the App from './App.vue' Import thBricks from 'TH-Bricks' Import ' TH-Bricks/dist/bundle.css' Import Router from './router' Import Store from ' ./store' createApp(App) .use(store) .use(router) .use(thBricks) .mount ( '#app' ) copying the code

App.vue

<template> < div id = "nav" > <!-- Use --> < t-text text = "hello" tag = "h2"/> < router-link to = "/" > Home </router- link > | < router-link to = "/about" > About </router-link > </div > < router-view/> </template> < Script lang = "TS" > Import {defineComponent} from 'VUE' Export default defineComponent ({ setup () { return {} } }) </script > copy code
  1. View Results

We can see that render the assembly pit: If the case can not be used to print thBricks occurs, you can restart the computer to try.

Publish npm

  1. First check if you are logged in
    npm whami
  2. If you are already logged in, skip directly, otherwise use
    npm login
    Log in, if you don t have an npm account, you need to register one
  3. release
    npm publish

You can see that the release has been successful.

We execute every time

npm publish
There is no guarantee that we will execute it
npm run build
, So is there any way to deal with it? After reviewing various materials, I found that it can be handled like this:

"scripts" : { "build" : "npm run clean && npm run build:esm && npm run build:umd" , "build:esm" : "rollup --config ./build/rollup.esm.config.js" , "build:umd" : "rollup --config ./build/rollup.umd.config.js" , "clean" : "rimraf ./dist" , "prepublishOnly" : "npm run build" //npm publish Execute npm run build first } Copy code

Write at the end

  • The basic component library process has basically been completed, but there is still a long way to go from a real perfect component library. It requires constant enrichment of component libraries, such as tree, table, message, and various project-specific components. and many more
  • Component library code