Vue使用Rollup编写tsx组件库
注意
这套配置方案遇到个问题:在我的家庭版 win10 系统中,rollup build 打包会报错 can not resolve xxx, 即无法解析 import 路径的问题,但是我尝试过,在我的专业版win10系统中没有问题,还有在 Ubuntu 系统中也没有问题;
这个问题很奇怪,似乎 rollup 对家庭版 win10 并不兼容,所以建议各位系统尽量使用专业版的windows系统
感谢以下资料
- 如使用Typescript撸Vue(Vue2 + TS +TSX+CSS module)
https://zhuanlan.zhihu.com/p/58351868
步骤
- 安装环境
安装以下3个辅助库,这便是关键,缺一不可,否则无法实现用 class 编写 tsx 的 vue 组件
yarn add vue-class-component -D
yarn add vue-property-decorator -D
yarn add vue-tsx-support -D
安装 sass 库(样式库看个人喜好,选择 less 还是 sass 无所谓)
yarn add node-sass -D
yarn add sass-loader -D
安装其他辅助库(主要参考下面给出的 package.json 脚本中的依赖即可,缺什么加什么)
yarn add -D rollup-plugin-typescript2
yarn add -D rollup-plugin-peer-deps-external
yarn add -D rollup-plugin-scss
...
创建 rollup 仓库
临时使用 rollup 针对 vue 的脚手架,快速创建 vue 的 rollup 组件库工程
在 vue-sfc-rollup 的步骤提示中,一定记得选择 typescript
npx vue-sfc-rollup在 entry.ts 中 import ts检查脚本
import "vue-tsx-support/enable-check";
- 我的 package.json 中的所有依赖,请按照我的配置,有些依赖一定要放到 peerDependencies 让 rollup 作为外部依赖进行打包处理
{
"name": "mq-components",
"version": "1.0.0",
"description": "",
"main": "dist/mq-components.ssr.js",
"browser": "dist/mq-components.esm.js",
"module": "dist/mq-components.esm.js",
"unpkg": "dist/mq-components.min.js",
"types": "mq-components.d.ts",
"files": [
"dist/*",
"mq-components.d.ts",
"src/**/*.tsx"
],
"scripts": {
"serve": "vue-cli-service serve dev/serve.ts",
"build": "cross-env NODE_ENV=production TARGET=web-standalone-dev rollup --config build/rollup.config.js",
"build:ssr": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format cjs",
"build:es": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format es",
"build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@babel/preset-typescript": "^7.9.0",
"@rollup/plugin-alias": "^2.2.0",
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-node-resolve": "^9.0.0",
"@rollup/plugin-replace": "^2.3.2",
"@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
"@vue/babel-preset-jsx": "^1.2.2",
"@vue/cli-plugin-babel": "^4.3.1",
"@vue/cli-plugin-typescript": "^4.3.1",
"@vue/cli-service": "^4.3.1",
"cross-env": "^7.0.2",
"minimist": "^1.2.5",
"node-sass": "^4.14.1",
"rollup": "^2.7.3",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-peer-deps-external": "^2.2.3",
"rollup-plugin-scss": "^2.6.1",
"rollup-plugin-terser": "^5.3.0",
"rollup-plugin-typescript2": "^0.28.0",
"rollup-plugin-vue": "^5.1.6",
"sass-loader": "^10.0.3",
"typescript": "^3.8.3",
"vue": "^2.6.11",
"vue-class-component": "^7.2.6",
"vue-property-decorator": "^9.0.2",
"vue-template-compiler": "^2.6.11",
"vue-tsx-support": "^2.3.3"
},
"peerDependencies": {
"element-ui": "^2.13.2",
"vue": "^2.6.11",
"vue-tsx-support": "^3.0.2"
},
"engines": {
"node": ">=10"
}
}
删除根目录下的 shims-tsx.d.ts ,否则会报重复定义的错误
vue-src-rollup 自动生成的 rollup.config.js 脚本中的代码都删除,然后写入我下面的配置脚本
// rollup.config.js
// 下面 import 的一些库,这里没用到,是原来 vue-sfc-rollup 自动生成的,
// 我没删除,是因为后续优化可能会用到,作为提醒自己,以免忘记
import fs from 'fs'
import path from 'path'
import vue from 'rollup-plugin-vue'
import external from 'rollup-plugin-peer-deps-external'
import typescript from 'rollup-plugin-typescript2'
import scss from 'rollup-plugin-scss'
import alias from '@rollup/plugin-alias'
import commonjs from '@rollup/plugin-commonjs'
import replace from '@rollup/plugin-replace'
import resolve from '@rollup/plugin-node-resolve'
import babel from 'rollup-plugin-babel'
import { terser } from 'rollup-plugin-terser'
import minimist from 'minimist'
const projectRoot = path.resolve(__dirname, '..')
const argv = minimist(process.argv.slice(2))
const globals = {
vue: "Vue" // 告诉rollup全局变量Vue即是vue
}
const ourPutDir = 'lib'
// default
let output = {
dir: ourPutDir,
format: 'es',
globals
}
// console.log(" argv.format = ",argv.format)
if (argv.format && argv.format === 'es') {
console.log(" es argv.format = ", argv.format);
output = {
dir: ourPutDir,
format: 'esm',
exports: 'named',
}
} else if (argv.format && argv.format === 'cjs') {
console.log(" cjs argv.format = ", argv.format);
output = {
compact: true,
dir: ourPutDir,
format: 'cjs',
name: 'MqComponents',
exports: 'named',
globals,
}
} else if (argv.format && argv.format === 'iife') {
console.log(" iife argv.format = ", argv.format)
output = {
compact: true,
dir: ourPutDir,
format: 'iife',
name: 'MqComponents',
exports: 'named',
globals,
}
}
export default {
input: 'src/index.ts',
output,
plugins: [
external(),
alias({
resolve: ['.js', '.jsx', '.ts', '.tsx'],
entries: {
'@': path.resolve(projectRoot, 'src'),
},
}),
scss({
output: path.resolve(projectRoot, ourPutDir + '/main.css'),
}),
typescript(),
resolve({
extensions: ['.ts', '.tsx', '.js', '.jsx']
}),
commonjs(),
babel({
exclude: 'node_modules/**',
extensions: ['.js', '.jsx', '.ts', '.tsx'],
presets: ["@vue/babel-preset-jsx"]
}),
]
}
- 最后可以在 src 下面编写自己的 tsx 脚本了,下面给出一份案例
【src/lib-components/template-sample/style.scss】
.container {
background-color: red;
}
【src/lib-components/template-sample/index.tsx】
import { Component } from 'vue-property-decorator';
import {
Component as TsComponent
} from "vue-tsx-support";
import './style.scss';
export interface ITemplateSampleProps{
}
@Component
export default class TemplateSample extends TsComponent{
protected render(){
return (hello every one)
}
}