Website information
Build a production version – library mode cn. Vitejs. Dev/guide/build…
Dev /config/#bui…
Technology stack
- vite
- rollup
packaging
Vue-cli comes with webpack, and the package size is a little big, while Vite comes with rollup, and the package size is very small. There are some instructions on the official website, so it is very convenient after learning.
Vite library projects fall into two categories :(my own)
- One is a pure JS project with no HTML;
- One is a project with HTML (templates), such as a UI library.
Here’s how to write and package them, but they’re pretty much the same.
Pure JS library project
Using Vite to create a project, here is a simple example:
// main.js
const toTypeString = (val) = > {
return Object.prototype.toString.call(val)
}
const typeName = (val) = > {
return Object.prototype.toString.call(val).replace(/^\[object (\S+)\]$/.'$1').toLowerCase()
}
const hasOwnProperty = Object.prototype.hasOwnProperty
const hasOwn = (val, key) = > hasOwnProperty.call(val, key)
const isFunction = (val) = > toTypeString(val) === '[object Function]'
const isAsync = (val) = > toTypeString(val) === '[object AsyncFunction]'
const isObject = (val) = >val ! = =null && typeof val === 'object'
const isArray = Array.isArray
const isString = (val) = > typeof val === 'string'
const isNumber = (val) = > typeof val === 'number'
const isBigInt = (val) = > typeof val === 'bigint'
const isBoolean = (val) = > typeof val === 'boolean'
const isRegExp = (val) = > toTypeString(val) === '[object RegExp]'
const isDate = (val) = > val instanceof Date
const isMap = (val) = > toTypeString(val) === '[object Map]'
const isSet = (val) = > toTypeString(val) === '[object Set]'
const isPromise = (val) = > toTypeString(val) === '[object Promise]'
const isSymbol = (val) = > typeof val === 'symbol'
const isNullOrUndefined = (val) = > {
if (val === null) return true
if (typeof val === 'undefined') return true
return false
}
function log(){
if (window.__showlog) console.log(... arguments) }const logTime = (msg, auto = true) = > {
const start = () = > {
if (window.__showlog) console.time(msg)
}
const end = () = > {
if (window.__showlog) console.timeEnd(msg)
}
if (auto) start() // Start the timer automatically
return { start, end }
}
export {
log, // Displays debugging information
logTime, / / timing
toTypeString, // Object.prototype.toString.call(val)
typeName, // Get a recognizable name
hasOwnProperty,
hasOwn,
isFunction, // Validate normal functions
isAsync, // Verify async functions
isPromise, / / Promise
isObject, / / Object
isArray, // Validate the array
isString, // Validate the string
isNumber, / / verification number
isBigInt, / / verification BigInt
isBoolean, // Verify Boolean
isRegExp, // Validate the re type
isDate, // Verify the date
isMap, / / map
isSet, / / validation set
isSymbol, / / verification Symbol
isNullOrUndefined // null or undefined returns true
}
Copy the code
The code is simple, just a demonstration.
To package, you can only have one export file, so the internal code structure has to be set up.
Library project with HTML
Pure JS is easy to handle, export output is good, then how to do with templates? It’s the same thing.
Create a project with Vite and create a test file:
// t-text.vue
- Template section:
<! -- Single line text -->
<template>
<el-input
v-model="value"
:id="'c' + columnId"
:name="'c' + columnId"
:size="size"
:clearable="clearable"
:validate-event="validate_event"
:show-word-limit="show_word_limit"
@blur="run"
@change="run"
@clear="run"
@input="myinput"
@keydown="clear"
>
</el-input>
Copy the code
- Code section
import { defineComponent } from 'vue'
// Add the UI library on demand (optional)
import { ElInput } from 'element-plus'
// Introduce the attributes required by the component, and the management class for the form's child controls
import { itemProps, itemController } from 'nf-ui-controller'
export default defineComponent({
name: 'el-form-item-text'.props: {
'el-input': ElInput,
modelValue: [String.Number],
...itemProps // Base attributes
},
emits: ['update:modelValue'],
setup (props, context) {
const {
value,
run,
clear,
myinput
} = itemController(props, context.emit)
return {
value,
run,
clear,
myinput
}
}
})
Copy the code
This is a repackaged library based on the UI library, using two third-party plug-ins:
- One is Element-Plus, which loads on demand.
- One is your own NF-UI-Controller library.
Then we set up an entry file main.js
import nfText from './t-text.vue'
export {
nfText
}
Copy the code
If you have many components, consider the structure, but this is just an example.
Set the vite. Config. Js
Once the code is written, you need to set up the viet.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' // Mainly used for alias file path alias
export default defineConfig({
plugins: [vue()],
// Package the configuration
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'), // Set the entry file
name: 'nf-tool'.// Use a name to install and import
fileName: (format) = > `nf-tool.${format}.js` // The packaged file name
},
sourcemap: true.// Prints the.map file
rollupOptions: {
// Be sure to externalize dependencies that you don't want packaged into the repository
external: ['vue'].output: {
Provide a global variable for these externalized dependencies in UMD build mode
globals: {
vue: 'Vue'}}}}})Copy the code
- Entry: Specifies the entry file to be packed.
- Name: indicates the package name
- FileName: specifies the name of the package file. The default value is umd and ES.
- Sourcemap: whether the.map file is generated. This is not generated by default. Set to true if necessary.
- RollupOptions: If the project references third-party plug-ins, you need to set exclusion here. Otherwise, the source code for third-party plug-ins will also be packaged, which makes the package file larger. Third party plugins will exist separately after exclusion.
Vite is packaged according to these Settings, and there are two modes of packaging:
- Umd: Packaged code is compact and small, but not easy to read;
- Es: The packaged code is very similar to the code we wrote, easy to read, but bulky.
How to handle third-party plug-ins
If your project uses a third-party plug-in, you need to set it in external:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' // Mainly used for alias file path alias
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
// Package the configuration
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'nf-ui-element-plus'.fileName: (format) = > `nf-ui-element-plus.${format}.js`
},
sourcemap: true.rollupOptions: {
// Be sure to externalize dependencies that you don't want packaged into the repository
external: ['vue'.'nf-ui-controller'.'element-plus'].// Notice here
output: {
Provide a global variable for these externalized dependencies in UMD build mode
globals: {
vue: 'Vue'.'nf-ui-controller': 'nfUIController'.'element-plus': 'elementPlus'}}}}})Copy the code
After this setting, the third-party plug-in code is referenced as import. If you don’t set this up, the code used in third-party plug-ins will be packaged together as internal project code, which will make the package bigger.
Set up the package. The json
Setting package.json is mainly for the description of the resource package when publishing. It needs to set the properties according to the requirements of NPM:
{
"name": "nf-tool"."version": "0.0.4"."description": "JavaScript widgets, validate JavaScript data types, output debugging information, etc."."keyword": "JavaScript typeof log"."files": ["dist"]."main": "./dist/nf-tool.umd.js"."module": "./dist/nf-tool.es.js"."exports": {
".": {
"import": "./dist/nf-tool.es.js"."require": "./dist/nf-tool.umd.js"}},"private": false."license": "MIT"."auther": "jin yang (jyk). Email: [email protected]"."scripts": {
"dev": "vite"."build": "vite build"."serve": "vite preview"
},
"dependencies": {
"@element-plus/icons": "^ 0.0.11"."element-plus": "^ 1.2.0 - beta. 3"."nf-tool": "^ 0.0.6"."vue": "^ 3.2.16"
},
"devDependencies": {
"@vitejs/plugin-vue": "^ 1.9.3." "."vite": "^" 2.6.4. ""}}Copy the code
If you do not want to install dependencies and devDependencies automatically, you need to remove dependencies and devDependencies.
packaging
Once set up, we can use YARN Build to package.
The packaged file looks like this:
- nf-tool-es.js
- nf-tool-umd.js
Publish resource packs to nPMjs.com
Here are the steps:
- Sign up at Npmjs.com;
- Go to the registered mailbox to activate the account;
- Open the terminal and use
npm login
Login; - use
npm publish
Release;
I won’t go into details for lack of space.
Installing resource Packs
I like to use YARN to install resource packs because it is faster.
yarn add nf-tool
Copy the code
The name set in package.json is the name used for the installation, so make it a good name and do not duplicate the existing name.
What if a project is a library project and needs to be published to a website?
Why is there such a need? Library projects, when writing, need a development environment, while writing code, while running to see the effect. Once written, it needs to be packaged as a library project. Do you then need a test environment, or a demo environment?
Setting up a project to write tests and demos would be a bit of a hassle, but it would be much easier if you could do it in one project. In this case, you need to set up a different viet.config.js.
The way of using comments before, it is more troublesome to change to change. It turns out that Vite provides a “mode” that allows you to do different Settings in vite.config.js.
Env file
Env.* files can be created to store different “modes” :
.env: development environment (default)
VITE_BASEURL=./
Copy the code
Env.project: test and presentation environment
VITE_BASEURL=nf-rollup-tool
Copy the code
.env.lib: library packaging
VITE_BASEURL=lib
Copy the code
Once the mode is set, let’s modify viet.config.js
Modify the vite. Config. Js
In viet.config. js, the different defineConfig alternatives are defined first, then loadEnv is used to read the mode value and return the corresponding defineConfig according to the mode.
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' // Mainly used for alias file path alias
const pathResolve = (dir) = > resolve(__dirname, '. ', dir)
// Publish library Settings
const lib = defineConfig({
plugins: [vue()],
// Package the configuration
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'nf-tool'.fileName: (format) = > `nf-tool.${format}.js`
},
sourcemap: true.rollupOptions: {
// Be sure to externalize dependencies that you don't want packaged into the repository
external: ['vue'].output: {
Provide a global variable for these externalized dependencies in UMD build mode
globals: {
vue: 'Vue'}}}}})// Development mode, production mode
const project = (url) = > {
return defineConfig({
plugins: [vue()],
devtools: true.resolve: {
alias: {
'/ @': resolve(__dirname, '. '.'src'),
'/nf-tool': pathResolve('lib/main.js') //}},base: url,
// Package the configuration
build: {
sourcemap: true.outDir: 'distp'.// Specify the output path to be separated from the library package
assetsDir: 'static/img/'.// Specify the path to generate static resources
rollupOptions: {
output: {
chunkFileNames: 'static/js1/[name]-[hash].js'.entryFileNames: 'static/js2/[name]-[hash].js'.assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
},
brotliSize: false./ / no statistics
target: 'esnext'.minify: 'esbuild' // Obfuscator, terser builds smaller files}}})}// loadEnv reads the schema and returns the corresponding defineConfig
export default ({ mode }) => {
const url = loadEnv(mode, process.cwd()).VITE_BASEURL
if (url === 'lib') {
// Package the library file
return lib
} else {
// Development mode, production mode
return project(url)
}
}
Copy the code
Note: You need to set up different output folders, otherwise they will overwrite each other.
Modify the package. Js
Sets the command to execute, followed by the desired mode.
"scripts": {
"dev": "vite"."build": "vite build --mode project"."lib": "vite build --mode lib"."serve": "vite preview"
}
Copy the code
This separates the different environments completely and allows you to add more patterns if there are other requirements.
The changed packaging command
yarn dev // Development environment
yarn build // Package and publish to the website, demo
yarn lib // Package library projects into resource bundles
Copy the code
So each performs its own duties, does not interfere with each other, also need not write all kinds of notes.