DevUI is a team with both a design perspective and an engineering perspective, serving HUAWEI CLOUD DevCloud The platform and several mid- and back-end systems within Huawei serve designers and front-end engineers.
Official website: devui.design
Ng component library: ng-devui (Welcome to Star)
Official Communication: Add DevUI Assistant (devui-official)
DevUIHelper Plugin: DevUIHelper-LSP (Welcome to Star)
foreword
With the prosperity of the front-end ecosystem, tool libraries are almost a necessity for efficient development. lodash/dayjs/numberal I believe everyone has used the useful tool library.
I'm currently developing Calendar Graph When Github submitted the calendar component, I found that there are many scenarios that need to deal with colors, such as judging whether a string is a valid color value, the mutual conversion of hex color value and rgb color value, etc., but I have not found one that can satisfy all of my needs. I need an open source library, so I decided to build a wheel myself.
this is to do ktools The reason for the tool library, this article will describe how to use Rollup This lightweight next-generation module bundler builds its own TypeScript tooling library.
By reading this article, you will learn:
- How to initialize a Rollup project
- How to configure Rollup and TypeScript
- How to script, build and publish your own repository to npm repository
1 Create and initialize a Github project
The first step in making an open source library is to create a Github (or Gitlab, etc.) code repository and perform a simple initialization, which mainly includes:
- Create a Git commit ignore configuration .gitignore
- Create Open Source License Statement LICENSE
- Initialize package.json
- Configure TypeScript tsconfig.json
- Configure Rollup rollup.config.js
1.1 Git commit ignore configuration
In order to prevent automatically generated directories/files such as node_modules from being submitted to the remote code repository, committing ignoring is the first thing to consider, and it can be simply configured in the early stage.
First create a .gitignore file
touch .gitignore
Add the following to the newly created .gitignore file:
# dependencies /node_modules # compiled output /dist
For detailed configuration, please refer to the official Github documentation: https://docs.github.com/en/free-pro-team@latest/github/using-git/ignoring-files
1.2 Create an open source agreement statement LICENSE
The open source protocol can be selected when creating the Github repository, or it can be added after the repository is created. Generally, the MIT protocol is selected.
Here is a little trick for adding protocols after creating a repository. Mainly divided into the following steps:
- Add a file to the Github repository
- Type LICENSE (note that it must be all uppercase)
- Choose an agreement
- submit
Step 1: Add a file to the Github repository
At the top right of the directory structure of the code repository, there is an Add file drop-down box, select the Create new file option in it, and enter the page for creating a new file.
Step 2: Enter "LICENSE"
Enter the full-size LICENSE in the file name, and a button Choose a license template will appear on the right side of the input box.
Step 3: Choose a protocol
Click the Choose a license template button to enter the page for choosing a license template.
We select MIT License in the left directory, and then enter the year and author's name in the right sidebar. You can see that the year and author after the Copyright (c) in the middle will change accordingly. Click the Review and submit button to return to the creation of the file. page, and automatically populate the LICENSE file with the content of the protocol you just selected.
Step 4: Submit
Click Commit new file at the bottom of the file creation page to submit the LICENSE file to the code repository.
After submitting, it will automatically jump to the LICENSE page, the effect is as follows:
1.3 Initialize package.json
After adding the two basic files .gitignore/LICENSE, the next step is to initialize the package.json file, which is the package configuration file for managing dependent packages and their versions, and is necessary for front-end projects.
We can create a default package.json with the following command:
npm init -y
Adding the -y parameter is not wanting to keep pressing Enterπ
The created package.json file is as follows:
{ "name": "ktools", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/kagol/ktools.git" }, "keywords": [], "author": "", "license": "MIT" }
We can simply modify and improve it.
name and version are the package name and version number respectively, which can be dynamically modified through scripts during subsequent releases, regardless.
description can be added as follows:
"description": "Front-end tool library"
main/scripts These will be discussed in detail in the chapter on building and deploying scripts later.
keywords/author can be added:
"keywords": [ "toolkit", "rollup", "typescript" ], "author": "Kagol",
After configuring package.json, the file will be automatically updated when the dependency package is installed later, which can be very convenient for dependency management.
1.4 Configure TypeScript tsconfig.json
TypeScript, a strongly typed language, is a good complement and enhancement to JavaScript. At present, the prospects are very good, and it must be used.
install tsc
We can quickly create a TypeScript default configuration file using the tsc command line tool.
First confirm whether tsc is installed, enter the command:
tsc -v
The following command appears indicating that it is not installed:
-bash: /usr/local/bin/tsc: No such file or directory
It can be installed globally with the following command:
npm i -g typescript
After successful installation, check the tsc version again:
$ tsc -v Version 4.1.2
Generate tsconfig.json configuration file
A default tsconfig.json configuration can be quickly generated using:
tsc --init
The resulting tsconfig.json file is as follows (commented code removed):
{ "compilerOptions": { /* Visit https://aka.ms/tsconfig.json to read more about this file */ /* Basic Options */ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ /* Strict Type-Checking Options */ "strict": true, /* Enable all strict type-checking options. */ /* Module Resolution Options */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ /* Advanced Options */ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ } }
The default configuration is actually enough, we do not modify it, and the configuration can be deleted later as needed.
1.5 Configure Rollup rollup.config.js
The last step in the initialization project is to configure Rollup. First, create a Rollup configuration file. Without the Rollup CLI tool, the initialization configuration file is not supported. It can only be created manually:
touch rollup.config.js
Then add the following to rollup.config.js:
import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; import typescript from 'rollup-plugin-typescript'; import pkg from './package.json'; export default { input: 'src/index.ts', // Packing entrance output: { // packaged for export file: pkg.browser, // The final packaged file path and file name are configured in the browser: 'dist/index.js' field of package.json format: 'umd', // umd is a universal packaging format compatible with amd/cjs/iife, suitable for browsers }, plugins: [ // Packaging plugins resolve(), // Find and package third-party modules in node_modules commonjs(), // Convert CommonJS to ES2015 modules for Rollup to process typescript() // Parse TypeScript ] };
Configure the browser field in package.json:
"browser": "dist/index.ts",
Install Rollup and TypeScript related dependencies:
npm i -D rollup typescript tslib rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-typescript
Note that the tslib library is also required because the rollup-plugin-typescript plugin depends on this library.
For the specific meaning of each configuration item in the Rollup configuration file, please refer to: https://www.rollupjs.com/guide/big-list-of-options
For the list of available plugins for Rollup, please refer to: https://github.com/rollup/plugins
2 Write the source code of the tool library
With the above initial project, you can officially start writing the source code of the tool method.
2.1 Go through process
First write a demo, run through the process of writing source code, building and packaging, and introducing and using it.
write source code
Our entry file is configured in src/index.ts, so we need to create this file first:
mkdir src touch src/index.ts
Then write some code in this file to test whether the packaging is normal:
console.log('hello ktools!');
build package
Enter the following command on the command line to package the project:
rollup -c
After execution, the packaged file index.js will be generated in the dist directory, with the following contents:
(function (factory) { typeof define === 'function' && define.amd ? define(factory) : factory(); }((function () { 'use strict'; console.log('hello ktools!'); })));
Introduce to use
At this time, we can casually introduce this empty shell tool library under a Vue/React/Angular project to see if it is normal:
For example, add the following code to the src/main.js of the Vue CLI project
import Vue from 'vue'; import App from './App.vue'; import router from './router'; import store from './store'; import ktools from '../index'; // The newly added code will output "hello ktools!" in the browser console Vue.config.productionTip = false; new Vue({ router, store, render: h => h(App), }).$mount('#app');
Or add to the src/main.ts file in the Angular CLI project:
import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import ktools from '../index'; console.log('ktools:', ktools); // This must be added to output "hello ktools!", since nothing is exported, ktools is printed as an empty object if (environment.production) { enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err));
2.2 Writing tool methods
After the process goes through, the tool method can be formally written.
Let's write a utility method that determines whether a string is a valid hex color value: isColor.
First create the src/is-color.ts file:
touch src/is-color.ts
Add the following:
/** * Determine if a string is a color value in hexadecimal * @param value */ const isColor = function(value: string): boolean { return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(value); } export default isColor;
Then add the code that introduces the is-color.ts file to the index.ts entry file:
import isColor from './is-color'; export { isColor, };
Re-execute rollup -c to build, and the generated dist/index.js is as follows:
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ktools = {})); }(this, (function (exports) { 'use strict'; /** * Determine if a string is a color value in hexadecimal * @param value */ var isColor = function (value) { return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(value); }; exports.isColor = isColor; Object.defineProperty(exports, '__esModule', { value: true }); })));
Then import into the project:
import { isColor } from '../index'; console.log('isColor #c6e48b:', isColor('#c6e48b')); // isColor #c6e48b: true console.log('isColor #c6e48:', isColor('#c6e48')); // isColor #c6e48: false
everything is normal!
3 Add build release script
At this point, our tool library ktools has been completed 90%, and the last step is to publish it to the npm repository, which can be manually published.
3.1 Manual release
Copy the package.json file to the dist directory, modify the version to the version number released this time, such as 0.0.1, and then enter the directory:
cd dist
Execute the following command to publish our ktools tool library to the npm repository:
npm publish
Waiting for the successful release with cheers, the result is an error, the following is the error message:
$ npm publish npm notice npm notice π¦ ktools@0.0.1 npm notice === Tarball Contents === npm notice 315B index.html npm notice 634B index.js npm notice 691B package.json npm notice === Tarball Details === npm notice name: ktools npm notice version: 0.0.1 npm notice package size: 1.1 kB npm notice unpacked size: 1.6 kB npm notice shasum: 35c3501906443ff46be51c2747c07e73136bf85c npm notice integrity: sha512-SZTM0msux0+Pt[...]IWmV6Gx5Tz41w== npm notice total files: 3 npm notice npm ERR! code E403 npm ERR! 403 403 Forbidden - PUT http://registry.npmjs.org/ktools - Package name too similar to existing packages; try renaming your package to '@kagol/ktools' and publishing with 'npm publish --access=public' instead npm ERR! 403 In most cases, you or one of your dependencies are requesting npm ERR! 403 a package version that is forbidden by your security policy. npm ERR! A complete log of this run can be found in: npm ERR! /Users/kagol/.npm/_logs/2020-12-05T05_42_31_632Z-debug.log
Looking at the prompt, it seems that the package name is repeated, and the prompt also kindly suggests renaming the package to @kagol/ktools before publishing it.
Then let's follow the prompts and try to change the name and add a scope:
"name": "ktools" -> "name": "@kagol/ktools",
After changing the name and republishing it, it was successful!
$ npm publish npm notice npm notice π¦ @kagol/ktools@0.0.1 npm notice === Tarball Contents === npm notice 22.0kB index.js npm notice 1.2kB package.json npm notice 1.8kB README.md npm notice === Tarball Details === npm notice name: @kagol/ktools npm notice version: 0.0.1 npm notice package size: 6.9 kB npm notice unpacked size: 25.0 kB npm notice shasum: d85994aecc86160862cef4f0033e5bfdaa136072 npm notice integrity: sha512-UEDEJEsMSXcMg[...]yY4KsXp4mXIBA== npm notice total files: 3 npm notice + @kagol/ktools@0.0.1
At this time, it can be formally installed and introduced into the project.
Install first:
npm i @kagol/ktools
The usage is the same as before, but the import method needs to be changed:
import { isColor } from '@kagol/ktools'; console.log('isColor #c6e48b:', isColor('#c6e48b')); // isColor #c6e48b: true console.log('isColor #c6e48:', isColor('#c6e48')); // isColor #c6e48: false
3.2 Publishing via script
Every time you publish, you have to copy the files, modify the package name, and change the version number, which is very troublesome. You can write a script to automate this process.
Mainly divided into the following steps:
- copy file
- Modify the file
- release
Step 1: Copy the file
Add a script for copying files to scripts in package.json:
"copy": "cp package.json README.md dist",
Step 2: Modify the file
Create a new scripts/publish.js file and add the following content:
const path = require('path'); const shelljs = require('shelljs'); const program = require('commander'); const targetFile = path.resolve(__dirname, '../dist/package.json'); const packagejson = require(targetFile); const currentVersion = packagejson.version; const versionArr = currentVersion.split('.'); const [mainVersion, subVersion, phaseVersion] = versionArr; // Default version number const defaultVersion = `${mainVersion}.${subVersion}.${+phaseVersion+1}`; let newVersion = defaultVersion; // Take the version number from the command line argument program .option('-v, --versions <type>', 'Add release version number', defaultVersion); program.parse(process.argv); if (program.versions) { newVersion = program.versions; } function publish() { shelljs.sed('-i', '"name": "ktools"', '"name": "@kagol/ktools"', targetFile); // Modify package name shelljs.sed('-i', `"version": "${currentVersion}"`, `"version": "${newVersion}"`, targetFile); // Modify version number shelljs.cd('dist'); shelljs.exec('npm publish'); // release } publish();
The two most important steps here:
- Modify package name
- Get the correct version number and modify
The modified file uses the shelljs library, and the version number parameter is used TJ Great God commander tool.
These two dependent libraries need to be installed in advance:
npm i -D shelljs commander
In addition, you need to add the build script command to package.json:
"build": "rollup -c && npm run copy",
Step 3: Publish
The publishing steps are relatively simple and have been placed in the publish.js script file.
Each release just needs to run the following commands in sequence:
npm run build npm run publish -- -v 0.0.2
In the future, you can consider integrating it into the pipeline to achieve fully automated deployment. Here you can refer to an article I wrote earlier: How does the big factory use the DevCloud pipeline to automate the deployment of Web applications?
4 Summary
This article introduces in detail the process and steps of using Rollup+TypeScript to create an open source tool library, and introduces how to configure Rollup and TypeScript, and how to write deployment scripts to automatically publish the tool library to the npm repository. I hope you like it, and welcome to give a Starπ encouragement. The following is the source code address of the ktools tool library:
https://github.com/kagol/ktools
Also welcome to light up the stars of our DevUI component library π
https://github.com/DevCloudFE/ng-devui
join us
We are the DevUI team, welcome to come here to create an elegant and efficient human-machine design/R&D system with us. Recruitment email: muyang2@huawei.com.
Text/DevUI Kagol
Recommended articles in the past
How does the big factory use the DevCloud pipeline to automate the deployment of Web applications? >