前言
vue-cli 自带的是 webpack 的打包方式,打出的包体积有点大,而 vite 自带的是 rollup 的打包方式,这种方式打包的体积就非常小,官网也有一些使用说明,所以学会之后还是比较很方便的。
依赖
依赖名称 | 依赖版本 | 依赖说明 |
---|---|---|
vite | ^2.9.9 | vue快速构建工具 |
@vitejs/plugin-vue | ^2.3.3 | vite支持打包vue插件 |
@vitejs/plugin-vue-jsx | ^1.3.10 | vite支持打包vue-jsx语法插件 |
autoprefixer | ^10.4.7 | 自动给css加上各浏览器前缀 |
vite-plugin-dts | ^1.2.0 | 打包类型声明文件 |
postcss-flexbugs-fixes | ^5.0.2 | 修复浏览器flex的一些bug |
详细配置
// vite.config.js
import {
defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import autoprefixer from 'autoprefixer';
import pff from 'postcss-flexbugs-fixes';
import dts from 'vite-plugin-dts';
import path from 'path';
import {
name} from './package.json';
export default defineConfig({
css: {
postcss: {
plugins: [autoprefixer({
overrideBrowserslist: [
"defaults",
"not ie < 8",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
],
grid: true,
}), pff]
}
},
plugins: [vue(), vueJsx(), dts()],
resolve: {
alias: {
'@': '/src'
},
},
build: {
minify: "terser",
brotliSize: true,
sourcemap: false,
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
},
keep_classnames: true,
},
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
name,
formats: ['es', 'cjs', 'umd'],
fileName: (format) => `${
name}.${
format}.js`
},
// assetsDir: 'assets',
outDir: 'dist',
rollupOptions: {
external: [
'vue',
'vuex',
'vue-router',
'axios',
'moment',
'mitt',
'js-cookie',
'crypto-js/aes',
'crypto-js/enc-utf8',
'crypto-js/pad-pkcs7',
'crypto-js/mode-ecb',
'crypto-js/md5',
'crypto-js/enc-utf8',
'crypto-js/enc-base64',
'ant-design-vue',
'@ant-design/icons-vue',
'lodash-es'
],
output: {
globals: {
"moment": "moment",
"vue": "vue",
"vue-router": "vueRouter",
"vuex": "vuex",
"js-cookie": "cookies",
"crypto-js/aes": "aes",
"crypto-js/enc-utf8": "UTF8",
"crypto-js/pad-pkcs7": "pkcs7",
"crypto-js/mode-ecb": "ECB",
"crypto-js/md5": "md5",
"crypto-js/enc-base64": "Base64",
"axios": "axios",
"ant-design-vue": "antDesignVue",
"mitt": "mitt",
"@ant-design/icons-vue": "$Icon",
"lodash-es": "lodashEs"
}
}
}
}
});
发布脚本
const fs = require('fs');
const pro = require('child_process');
class Publish {
constructor(config) {
this._config = {
pkg: 'package.json',
version: '',
versionRule: /^([1-9]\d|[1-9])(.([1-9]\d|\d)){2}$/,
versionAuto: {
step: 1,
main: false,
secondary: false,
revise: true
},
cpList: ['package.json', 'README.md'],
dir: 'dist',
command: {
build: 'npm run build:vite',
publish: 'npm publish'
},
package: {
}
};
Object.assign(this._config, config);
this._pkg = JSON.parse(fs.readFileSync(this._config.pkg).toString());
Object.assign(this._pkg, this._config.package);
if (this._config.version) {
this._assert(!this._checkVersion(this._config.version), "config中version属性不符合规范");
} else {
this._assert(!this._checkVersion(this._pkg.version), "package.json中version属性不符合规范");
}
}
/**
* 版本号转换
* @param {string|{r: number, s: number, m: number}} version 版本号
* @returns {string|{r: number, s: number, m: number}}
*/
_transform(version) {
if (typeof version === 'string') {
const [m, s, r] = version.split('.');
return {
m: parseInt(m), s: parseInt(s), r: parseInt(r)
};
} else {
const {
m, s, r} = version;
return `${
m}.${
s}.${
r}`;
}
}
/**
* 验证版本号是否符合规范
* @param {string} version 版本号
* @returns {boolean}
*/
_checkVersion(version) {
return this._config.versionRule.test(version);
}
/**
* 断言
* @param {boolean} b
* @param {string} m
*/
_assert(b, m) {
if (b) {
throw Error(m);
}
}
/**
* 迭代版本
*/
_version() {
function versionSwap(newVersion) {
this._pkg.oldVersion = this._pkg.version;
this._pkg.version = newVersion;
fs.writeFileSync(this._config.pkg, JSON.stringify(this._pkg));
console.log(`+ 迭代版本 -> ${
this._pkg.version}`);
console.log(`+ 历史版本 -> ${
this._pkg.oldVersion}`);
}
if (this._config.version) {
versionSwap.call(this, this._config.version);
console.log(`+ 设置版本 -> ${
this._config.version}`);
} else {
const {
m, s, r} = this._transform(this._pkg.version);
const {
main, secondary, revise, step} = this._config.versionAuto;
versionSwap.call(this, this._transform({
m: main ? m + step : m,
s: secondary ? s + step : s,
r: revise ? r + step : r
}));
}
}
/**
* 移动文件到指定目录
*/
_copyFiles() {
const {
cpList, dir} = this._config;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
cpList.forEach(src => {
fs.copyFileSync(src, `${
dir}/${
src}`);
console.log(`+ 文件拷贝 - ${
src} -> ${
dir}/${
src}`);
});
}
/**
* 执行...
*/
exec() {
const {
dir, command} = this._config;
let result;
console.log(`--------------------[依赖包清除开始]--------------------`);
result = pro.execSync(`npm rm -rf ${
dir}`);
console.log(result.toString());
console.log(`--------------------[依赖包构建开始]--------------------`);
result = pro.execSync(`${
command.build}`);
console.log(result.toString());
console.log(`---------------------[版本迭代开始]---------------------`);
this._version();
console.log(`---------------------[文件拷贝开始]---------------------`);
this._copyFiles();
console.log(`--------------------[依赖包发布开始]--------------------`);
result = pro.execSync(`cd ${
dir} && ${
command.publish}`);
console.log(result.toString());
}
static run(config) {
try {
console.log(`=================[一键发布脚本执行开始]=================`);
new Publish(config).exec();
console.log(`=================[一键发布脚本执行结束]=================`);
} catch (e) {
console.error(e);
}
}
}
Publish.run();
构建命令
{
"scripts":{
"build:vite": "npm rm -rf dist && vite build --config vite.config.js",
"build:publish": "cls && node publish.js"
},
"main": "cmt-vue-lib.cjs.js",
"module": "cmt-vue-lib.es.js",
"browser": "cmt-vue-lib.umd.js",
"typings": "index.d.js",
"peerDependencies": {
"@ant-design/icons-vue": "^6.1.0",
"ant-design-vue": "^3.2.5",
"axios": "^0.26.1",
"crypto-js": "^4.1.1",
"js-cookie": "^3.0.1",
"lodash-es": "^4.17.21",
"mitt": "^3.0.0",
"moment": "^2.29.3",
"vue": "^3.2.13",
"vue-router": "^4.0.3",
"vuex": "^4.0.0"
}
}
常见问题
-
在标签上使用资源路径,打包后资源不存在的问题。需要以import的形式导入资源。
-
导入图片相关资源报错问题。需要增加声明文件images.d.ts
// images.d.ts declare module '*.svg'; declare module '*.png'; declare module '*.jpg'; declare module '*.jpeg'; declare module '*.gif'; declare module '*.bmp'; declare module '*.tiff';
-
用vite打包成lib库图片资源不会分离出来,它将会以base64编码形式存放在css中。
组件库类型
定义类型
// 组件库类型
export interface XUIComponents {
XLayout: typeof Layout;
XLayoutContent: typeof LayoutContent;
XLayoutSlider: typeof LayoutSlider
XCard: typeof Card;
XCardBody: typeof CardBody;
XCardFooter: typeof CardFooter;
XCardHeader: typeof CardHeader;
XCardTitle: typeof CardTitle;
XModal: typeof Modal;
XEllipsis: typeof Ellipsis;
XEmpty: typeof Empty;
XIcon: typeof Icon;
XIconSelector: typeof IconSelector;
}
// vue3 globalConfig
export interface XUIProperties {
$xSoft: ICmSoft;
$xSysSvr: SystemStoreService;
$xUserSvr: UserStoreService;
$xMsgSvr: MessageApi;
$xModalSvr: typeof AntdModal;
$xRequest: VAxios;
$xWebCache: WebStorage;
$xConfig: ISoftConfig;
}
// vue3 options扩展
export interface XUIOptions {
title?: string;
single?: boolean;
}
安装类型
declare module 'vue' {
interface GlobalComponents extends CmUIComponents {
}
}
declare module '@vue/runtime-core' {
interface ComponentCustomProperties extends CmUIProperties {
}
interface ComponentCustomOptions extends CmUIOptions{
}
}