官网资料

构建生产版本——库模式

https://cn.vitejs.dev/guide/build.html#library-mode

详细设置

https://cn.vitejs.dev/config/#build-lib

技术栈

  • vite
  • rollup

打包方式

vue-cli 自带的是 webpack 的打包方式,打出的包体积有点大,而 vite 自带的是 rollup 的打包方式,这种方式打包的体积就非常小,官网也有一些使用说明,所以学会之后还是比较很方便的。

vite 的库项目可以分为两类:(我自己分的)

  • 一个是纯js的项目,不带HTML;
  • 一个是可以带上HTML(模板)的项目,比如UI库。

下面分别介绍一下编写和打包方式,其实大同小异。

纯js的库项目

使用 vite 建立项目,这里举一个简单的例子:

// 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() // 自动开始计时
return { start, end }
} export {
log, // 打印调试信息
logTime, // 计时
toTypeString, // Object.prototype.toString.call(val)
typeName, // 获取可以识别的名称 hasOwnProperty,
hasOwn, isFunction, // 验证普通函数
isAsync, // 验证 async 的函数
isPromise, // 验证 Promise
isObject, // 验证 Object
isArray, // 验证数组
isString, // 验证字符串
isNumber, // 验证 number
isBigInt, // 验证 BigInt
isBoolean, // 验证 布尔
isRegExp, // 验证正则类型
isDate, // 验证日期
isMap, // 验证 map
isSet, // 验证 set
isSymbol, // 验证 Symbol isNullOrUndefined // null 或者 undefined 返回 true
}

代码比较简单,仅仅只是演示。

想要打包的话,只能有一个出口文件,所以内部的代码结构要设置好。

带HTML的库项目

纯js的好办了,export 输出就好,那么带模板的怎么办呢?其实也是一样的。

用 vite 建立一个项目,建立一个测试文件:

// t-text.vue

  • 模板部分:
<!--单行文本-->
<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>
  • 代码部分
  import { defineComponent } from 'vue'
// 按需索取的方式引入UI库(非必须)
import { ElInput } from 'element-plus'
// 引入组件需要的属性、表单子控件的管理类
import { itemProps, itemController } from 'nf-ui-controller' export default defineComponent({
name: 'el-form-item-text',
props: {
'el-input': ElInput,
modelValue: [String, Number],
...itemProps // 基础属性
},
emits: ['update:modelValue'],
setup (props, context) {
const {
value,
run,
clear,
myinput
} = itemController(props, context.emit) return {
value,
run,
clear,
myinput
}
}
})

这是基于UI库做的二次封装的库,使用了两个第三方插件:

  • 一个是 element-plus,采用按需加载的方式;
  • 一个是自己做的 nf-ui-controller 库。

然后我们设置一个入口文件 main.js

import nfText from './t-text.vue'

export {
nfText
}

如果有很多组件的话,就要考虑好结构,这里只是举个例子。

设置vite.config.js

代码写好之后,需要设置一下 vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' // 主要用于alias文件路径别名 export default defineConfig({
plugins: [vue()],
// 打包配置
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'), // 设置入口文件
name: 'nf-tool', // 起个名字,安装、引入用
fileName: (format) => `nf-tool.${format}.js` // 打包后的文件名
},
sourcemap: true, // 输出.map文件
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
}
})
  • entry:指定要打包的入口文件。
  • name:包的名称
  • fileName:包文件的名称,默认是umd和es两个文件。
  • sourcemap:是否生成 .map 文件,默认是不会生成的,如果需要的话需要设置为 true。
  • rollupOptions:如果项目引用了第三方插件,那么需要在这里设置排除,如果不设置的话,第三方插件的源码也会被打包进来,这样打包文件就变大了。排除之后第三方的插件会单独存在。

vite 会按照这里的设置进行打包,打包分为两种模式:

  • umd:打包后代码很紧凑、体积小,但是不易读;
  • es:打包后的代码和我们写的代码很像,易读,但是体积大。

第三方插件的处理方式

如果项目使用了第三方的插件,那么需要在 external 里面做设置:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' // 主要用于alias文件路径别名 // https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
// 打包配置
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'nf-ui-element-plus',
fileName: (format) => `nf-ui-element-plus.${format}.js`
},
sourcemap: true,
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue','nf-ui-controller','element-plus'], // 注意看这里
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue',
'nf-ui-controller': 'nfUIController',
'element-plus': 'elementPlus'
}
}
}
}
})

设置之后,第三方插件的代码,会以 import 的方式被引用。

如果不做设置的话,就会把第三方插件里面使用到的代码,拿出来作为项目内部代码一起被打包,这样包的体积就变大了。

设置package.json

设置 package.json 主要是发布的时候做资源包的说明,需要按照 npm 的要求设置属性:

{
"name": "nf-tool",
"version": "0.0.4",
"description": "JavaScript 的小工具,验证 JavaScript 的数据类型,输出调试信息等。",
"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: jyk0013@163.com",
"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"
}
}

如果在安装资源包的时候,不想自动安装第三方插件的话,需要去掉 dependencies 和 devDependencies,否则会自动安装里面涉及到的第三方插件。

打包

设置好之后我们可以用 yarn build 进行打包。

打包后的文件是这种风格:

  • nf-tool-es.js

  • nf-tool-umd.js

发布资源包到 npmjs.com

简单介绍一下步骤:

  • 先到 npmjs.com 网站注册账号;
  • 到注册邮箱激活账号;
  • 打开终端,使用 npm login登录;
  • 使用 npm publish 发布;

篇幅有限,细节就不介绍了。

安装资源包

我喜欢使用 yarn 安装资源包,因为速度更快一些。

yarn add nf-tool

package.json 里面设置的名称就是安装用的名称,所以要起个好的名称,另外不能和现有的名称重复。

如果一个项目即是库项目,又需要发布到网站怎么办?

为啥会有这样的需求?

库项目在编写的时候,需要一个开发环境,一边写代码,一边运行看效果。

写好之后需要按库项目的方式打包。

然后是不是需要一个测试环境,或者演示环境?

如果再建立一个项目写测试和演示,那么就有点麻烦了,如果可以在一个项目搞定就方便多了。

这个时候就需要设置不同的 vite.config.js 。

之前使用注释的方式,改来改去的比较麻烦。现在发现 vite 提供了“模式”的方式,允许我们在 vite.config.js 里面做不同的设置。

设置.env文件

按照官网的说明,我们可以建立多个 .env.* 文件,来存放不同的“模式”:

.env : 开发环境(默认)

VITE_BASEURL=./

.env.project : 测试、演示环境

VITE_BASEURL=nf-rollup-tool

.env.lib : 库打包

VITE_BASEURL=lib

模式设置好之后我们来修改 vite.config.js

修改 vite.config.js

在 vite.config.js 里面,首先定义不同的 defineConfig 备用,然后使用 loadEnv 读取模式值,根据模式返回对应的 defineConfig。

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' // 主要用于alias文件路径别名
const pathResolve = (dir) => resolve(__dirname, '.', dir) // 发布库的设置
const lib = defineConfig({
plugins: [vue()],
// 打包配置
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'nf-tool',
fileName: (format) => `nf-tool.${format}.js`
},
sourcemap: true,
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
}
}) // 开发模式、生产模式
const project = (url) => {
return defineConfig({
plugins: [vue()],
devtools: true,
resolve: {
alias: {
'/@': resolve(__dirname, '.', 'src'),
'/nf-tool': pathResolve('lib/main.js') //
}
},
base: url,
// 打包配置
build: {
sourcemap: true,
outDir: 'distp', // 指定输出路径,要和库的包区分开
assetsDir: 'static/img/', // 指定生成静态资源的存放路径
rollupOptions: {
output: {
chunkFileNames: 'static/js1/[name]-[hash].js',
entryFileNames: 'static/js2/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
},
brotliSize: false, // 不统计
target: 'esnext',
minify: 'esbuild' // 混淆器,terser构建后文件体积更小
}
}
})
} // 用 loadEnv 读取模式,然后返回对应的 defineConfig
export default ({ mode }) => {
const url = loadEnv(mode, process.cwd()).VITE_BASEURL
if (url === 'lib') {
// 打包库文件
return lib
} else {
// 开发模式、生产模式
return project(url)
}
}

注意:需要设置不同的输出的文件夹,否则会互相覆盖。

修改 package.js

设置执行的命令,后面加上需要的模式。

  "scripts": {
"dev": "vite",
"build": "vite build --mode project",
"lib": "vite build --mode lib",
"serve": "vite preview"
}

这样就可以把不同的环境完全分开了,如果有其他的需求,还可以增加更多的模式。

更改后的打包命令

yarn dev  // 开发环境
yarn build // 打包发布到网站,演示
yarn lib // 打包库项目,做成资源包

这样各司其职,互不干扰,也不用各种写注释了。

vite的项目,使用 rollup 打包的方法的更多相关文章

  1. 什么,你还使用 webpack?别人都在用 vite 搭建项目了

    一.vite 到底是干嘛的? vite 实际上就是一个面向现代浏览器,基于 ES module 实现了一个更轻快的项目构建打包工具. vite 是法语中轻快的意思. vite 的特点: 1.轻快的冷服 ...

  2. Atitit.项目修改补丁打包工具 使用说明

    Atitit.项目修改补丁打包工具 使用说明 1.1. 打包工具已经在群里面.打包工具.bat1 1.2. 使用方法:放在项目主目录下,执行即可1 1.3. 打包工具的原理以及要打包的项目列表1 1. ...

  3. vue项目通过webpack打包生成的dist文件放到express环境里运行(vue+webpack+express)

    1.首先需要的原料肯定是vue打包生成的dist文件 在vue项目目录下运行:npm run build,等待运行结束,会在项目目录下生成一个dist文件夹,里面会生成一些文件(如下图示) 小的项目文 ...

  4. maven+springboot项目使用idea打包

    首先简单了解一下maven: 概述 日常开发中,我们用到的maven相关功能大概以下几种: 1. 管理jar依赖 2. 构建项目(打包.编译等) 3. 发布项目(共享.上传至服务器,供他人使用) 简单 ...

  5. Qt程序打包发布方法(使用官方提供的windeployqt工具)

    Qt程序打包发布方法(使用官方提供的windeployqt工具) 转自:http://tieba.baidu.com/p/3730103947?qq-pf-to=pcqq.group Qt 官方开发环 ...

  6. springBoot 项目 jar/war打包 并运行

    一:idea  打jar  包 简述:springboor  项目最好的打包方式就是打成jar  ,下边就是简单的过程 1.打开idea工具 ,选着要打开的项目, 然后打开view--> too ...

  7. Vue老项目支持Webpack打包

    1.老的vue项目支持webpack打包 最近在学习Vue.js.版本是2.6,webpack的版本也相对较老,是2.1.0版本.项目脚手架只配置了npm run dev和npm run build. ...

  8. SSH项目与SSM项目的进入首页的方法

    SSH项目中: jsp页面一般都是存放在WEB-INF下面的目录下,这样我们就不能直接访问到这些jsp页面了,保证了页面的安全性. 在struts的管理中,是利用action来实现页面的跳转,进入in ...

  9. ThinkPHP公共配置文件与各自项目中配置文件组合的方法

    ThinkPHP公共配置文件与各自项目中配置文件组合的方法 文章TAG:thinkphp 公共配置文件 时间:2014-11-25来源:www.aspku.com 作者:源码库 文章热度: 146 ℃ ...

随机推荐

  1. Win10 配置JDK1.8 (JDK 8)环境变量

    JDK的安装: 1. JDK安装过程中,一般X掉公共JRE,因为JDK包含了JRE:     环境变量的配置: 1. 打开环境变量,编辑系统变量,新建: 变量名:JAVA_HOME 变量值:D:\so ...

  2. oo第一单元学习总结

    写在开头: 第一次接触面向对象思想和java语言,在学习以及完成作业的过程经历了一个比较痛苦的过程, 虽然在每次写作业时总是会有一些小小的抱怨,虽然写出的代码还是很差, 但是看到自己有所进步,还是感觉 ...

  3. 【做题记录】CF1444A Division

    CF1444A Division 题意: 给定 \(t\) 组询问,每组给两个数 \(p_i\) 和 \(q_i\) ,找出最大的整数 \(x_i\) ,要求 \(p_i\) 可被 \(x_i\) 整 ...

  4. 架构师之路-redis集群解析

    引子 上篇<架构师之路-https底层原理>里我提到了上面的整体视图,文章也介绍了想要真正能在工作中及时正确解决问题的基本功:原理理解透彻.今天以redis集群解析为例介绍一个及时敏锐的发 ...

  5. 基于SpringBoot项目MyBatis分页插件实现分页总结

    前言 在使用Mybatis时,最头痛的就是写分页了,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 se ...

  6. ICMP 协议仿真及ping命令用途

    1.实验目的 加深对 IPv4 协议首部各定义域的理解,掌握路由表的结构和基本配置命令,熟悉 ICMP 的调试操作. 2.实验原理 IPv4 协议定义,网络层协议的相关 RFC 定义和描述. 3.实验 ...

  7. The art of multipropcessor programming 读书笔记-3. 自旋锁与争用(2)

    本系列是 The art of multipropcessor programming 的读书笔记,在原版图书的基础上,结合 OpenJDK 11 以上的版本的代码进行理解和实现.并根据个人的查资料以 ...

  8. k8s入坑之路(12)ingress-nginx安装配置四层代理

    ingress官方文档地址:http://docs.kubernetes.org.cn/  https://feisky.gitbooks.io/kubernetes/content/plugins/ ...

  9. 【java+selenium3】元素的扩展操作(二)

    1.判断当前元素是否可显示 isDisplay(); //判断元素是否可见 boolean a= driver.findElement(By.id("xxx")).isDispla ...

  10. 攻防世界 WEB 高手进阶区 easytornado Writeup

    攻防世界 WEB 高手进阶区 easytornado Writeup 题目介绍 题目考点 Python模板 tornado 模板注入 Writeup 进入题目, 目录遍历得到 /flag.txt /w ...