From cd5998fdb08c634e51c294d5448bbd3e25427844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=B3=A2?= <18310915680@163.com> Date: Sun, 4 Sep 2022 13:37:32 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BD=BF=E7=94=A8esbuild=E6=89=93=E5=8C=85?= =?UTF-8?q?=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 232d2c2..1ea24a1 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,12 @@ -# Rollup + Typescript + Vue3.0组件库模板 +# Esbuild + Typescript + Vue3.0组件库模板 ## 功能介绍 -- rollup模块化打包 - typescript - esbuild打包编译 -- jest + @vue/test-utils 组件测试 - eslint代码规范检查 - sass,postcss预处理 +- browserSync本地开发服务 -## 使用Stylus/Less -默认支持Sass预处理,如需使用Stylus/Less,安装对应的解析器 -- Stylus: `yarn add -D stylus` -- Less: `yarn add -D less` ## 开发指南 请使用wecoder-cli初始化使用 ``` @@ -24,9 +19,9 @@ npm install -g wecoder-cli wecoder init # 1.项目基本配置 -# 2.选择基于rollup的vue3.0组件库模板 +# 2.选择基于esbuild的vue3.0组件库模板 # 3.等待初始化完成 -# 4.修改examples/main.ts中引入文件的路径(将“[name]”替换为打包后的js名称) +# 4.修改esbuild.config.js中libraryName变量为包的名 cd ``` @@ -44,12 +39,6 @@ npm run dev yarn dev ``` -单元测试 -``` -npm run test -# or -yarn test -``` 生产打包 ``` @@ -61,25 +50,23 @@ yarn build ## 目录结构 ``` ... -packages -------------- 组件库源码 - - Button ------------- 组件目录 - - index.ts ---------- 组件注册入口 - - src --------------- 组件源码 +packages --------------- 组件库源码 + - components ---------- 组件目录 + - Button ------------- 组件目录 + - index.ts ---------- 组件注册入口 + - src --------------- 组件源码 - index.ts ----------- 组件库打包入口文件 examples -------------- 开发预览页面源码 - main.ts ------------ 预览页入口文件 - App.vue ------------ 预览页入口组件 - index.html --------- 预览页htlm模板 -tests ----------------- 单元测试目录 - - **/*.spec.ts ------- 单元测试文件 types ----------------- ts注解文件目录 .editorconfig --------- 编辑器配置文件 .eslintignore --------- eslint检查忽略目录 .eslintrc ------------- eslint检查配置文件 -jest.config.js -------- jest测试配置文件 -rollup.config.js ------ rollup配置文件 +esbuild.config.js ------ esbuild配置文件 tsconfig.json --------- ts编译配置文件 -components.json ------- 单组件映射表 +components.js --------- 单组件映射表 ... ``` -- Gitee From 79073aa15542532cb841e8eb7460fb8397c1b0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=B3=A2?= <18310915680@163.com> Date: Sun, 4 Sep 2022 13:38:12 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 3 +- .eslintignore | 2 +- .eslintrc | 89 +- .gitignore | 2 +- components.js | 4 + components.json | 6 - config/rollup.bundle.js | 57 - config/rollup.components.js | 67 - config/rollup.config.js | 81 - config/rollup.dev.js | 55 - esbuild.config.js | 155 + examples/App.vue | 71 +- examples/index.html | 2 + examples/main.ts | 5 +- jest.config.js | 22 - package.json | 134 +- packages/Button/src/index.vue | 92 - packages/assets/scss/button.scss | 2 +- packages/assets/scss/index.scss | 2 +- packages/{ => components}/Button/index.ts | 7 +- packages/components/Button/src/FaButton.vue | 68 + packages/components/Icon/index.ts | 10 + packages/components/Icon/src/FaIcon.vue | 12 + packages/index.ts | 20 +- tests/Button/button.spec.ts | 21 - tests/index.spec.ts | 10 - tests/shim-vue.d.ts | 5 - tsconfig.json | 80 +- types/index.d.ts | 2 - yarn.lock | 8398 ++++--------------- 30 files changed, 2148 insertions(+), 7336 deletions(-) create mode 100644 components.js delete mode 100644 components.json delete mode 100644 config/rollup.bundle.js delete mode 100644 config/rollup.components.js delete mode 100644 config/rollup.config.js delete mode 100644 config/rollup.dev.js create mode 100644 esbuild.config.js delete mode 100644 jest.config.js delete mode 100644 packages/Button/src/index.vue rename packages/{ => components}/Button/index.ts (36%) create mode 100644 packages/components/Button/src/FaButton.vue create mode 100644 packages/components/Icon/index.ts create mode 100644 packages/components/Icon/src/FaIcon.vue delete mode 100644 tests/Button/button.spec.ts delete mode 100644 tests/index.spec.ts delete mode 100644 tests/shim-vue.d.ts diff --git a/.editorconfig b/.editorconfig index 75e735c..0339871 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,8 +3,7 @@ root = true [*] charset = utf-8 indent_size = 2 -indent_style = tab -tab_width = 2 +indent_style = space insert_final_newline = true end_of_line = lf trim_trailing_whitespace = true diff --git a/.eslintignore b/.eslintignore index 5fd8893..1823be4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,5 +3,5 @@ dist node_modules tests types -examples/index.html +examples/static coverage diff --git a/.eslintrc b/.eslintrc index 0bba8ee..1c470c1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,47 +1,46 @@ { - "root": true, - "env": { - "node": true, - "browser": true - }, - "globals": { - "window": true, - "process": true - }, - "parser": "vue-eslint-parser", - "parserOptions": { - "parser": "@typescript-eslint/parser", - "sourceType": "module" - }, - "plugins": ["@typescript-eslint"], - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:vue/vue3-recommended", - "eslint:recommended" - ], - "rules": { - "no-tabs": "off", - "indent": ["error", "tab"], - "quotes": ["error", "single"], - "comma-dangle": "error", - "semi": ["error", "never"], - "comma-spacing": "error", - "key-spacing": "error", - "keyword-spacing": "error", - "arrow-spacing": "error", - "block-spacing": ["error", "always"], - "object-curly-spacing": ["error", "always"], - "switch-colon-spacing": "error", - "space-before-blocks": "error", - "space-before-function-paren": "error", - "spaced-comment": "error", - "no-trailing-spaces": "error", - "space-infix-ops": ["error", { "int32Hint": false }], - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/ban-types": "off", - "vue/require-default-prop": "off", - "vue/require-explicit-emits": "off" - } + "root": true, + "env": { + "node": true, + "browser": true + }, + "globals": { + "window": true, + "process": true + }, + "parser": "vue-eslint-parser", + "parserOptions": { + "parser": "@typescript-eslint/parser", + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:vue/vue3-recommended" + ], + "rules": { + "no-tabs": "off", + "indent": ["error", 2], + "quotes": ["error", "single"], + "comma-dangle": "error", + "semi": ["error", "never"], + "comma-spacing": "error", + "key-spacing": "error", + "keyword-spacing": "error", + "arrow-spacing": "error", + "block-spacing": ["error", "always"], + "object-curly-spacing": ["error", "always"], + "switch-colon-spacing": "error", + "space-before-blocks": "error", + "space-before-function-paren": "error", + "spaced-comment": "error", + "no-trailing-spaces": "error", + "space-infix-ops": ["error", { "int32Hint": false }], + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/ban-types": "off", + "vue/require-default-prop": "off", + "vue/require-explicit-emits": "off" + } } diff --git a/.gitignore b/.gitignore index 844ea2d..819aee4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ lib -dist +examples/static node_modules coverage diff --git a/components.js b/components.js new file mode 100644 index 0000000..ec8c4e0 --- /dev/null +++ b/components.js @@ -0,0 +1,4 @@ +export default { + 'button': './packages/components/Button/index.ts', + 'icon': './packages/components/Icon/index.ts' +} diff --git a/components.json b/components.json deleted file mode 100644 index 44d0bc8..0000000 --- a/components.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "componentsMaps": { - "button": "./packages/Button/index.ts" - }, - "webComponents": [] -} diff --git a/config/rollup.bundle.js b/config/rollup.bundle.js deleted file mode 100644 index a7de48a..0000000 --- a/config/rollup.bundle.js +++ /dev/null @@ -1,57 +0,0 @@ -import path from 'path' -import postcss from 'postcss' -import scss from 'rollup-plugin-scss' -import copy from 'rollup-plugin-copy' -import { name } from '../package.json' -import autoprefixer from 'autoprefixer' -import postcssPresetEnv from 'postcss-preset-env' -import postcssMinify from 'postcss-minify' -import postcssImport from 'postcss-import' - -const file = (type = 'min') => path.resolve(__dirname, `../lib/${name}.${type}.js`) - -export default function (commonRollupPlugins, isProduct) { - return { - input: path.resolve(__dirname, '../packages/index.ts'), - output: [ - { - name, - file: file('esm'), - format: 'es', - exports: 'auto', - sourcemap: !isProduct - }, - { - name, - file: file('umd'), - format: 'umd', - globals: { - 'vue': 'Vue' - }, - sourcemap: !isProduct, - exports: 'named' - } - ], - plugins: [ - scss({ - output: `lib/css/${name}.min.css`, - prefix: '@import "./variable";', - processor: () => postcss([ - autoprefixer(), - postcssPresetEnv(), - postcssMinify(), - postcssImport() - ]), - sass: require('node-sass') - }), - ...commonRollupPlugins, - copy({ - targets: [{ - src: path.resolve(__dirname, '../packages/assets/fonts/*'), - dest: path.resolve(__dirname, '../lib/fonts') - }] - }) - ], - external: ['vue'] - } -} diff --git a/config/rollup.components.js b/config/rollup.components.js deleted file mode 100644 index bab62c0..0000000 --- a/config/rollup.components.js +++ /dev/null @@ -1,67 +0,0 @@ -import path from 'path' -import postcss from 'postcss' -import scss from 'rollup-plugin-scss' -import components from '../components.json' -import autoprefixer from 'autoprefixer' -import postcssPresetEnv from 'postcss-preset-env' -import postcssMinify from 'postcss-minify' -import postcssImport from 'postcss-import' - -export default function (commonRollupPlugins) { - const { componentsMaps, webComponents } = components - const configList = [] - for (const [fileName, input] of Object.entries(componentsMaps)) { - const isWebComponent = webComponents.findIndex(name => name === fileName) > -1 - if (isWebComponent) { - configList.push({ - input, - output: { - name: fileName, - file: path.resolve(__dirname, `../lib/components/${fileName}.js`), - format: 'iife', - extend: true, - exports: 'named' - }, - plugins: [ - scss({ - output: false, - processor: () => postcss([ - autoprefixer(), - postcssPresetEnv(), - postcssImport() - ]), - sass: require('node-sass') - }), - ...commonRollupPlugins - ] - }) - } else { - configList.push({ - input, - output: { - name: fileName, - file: path.resolve(__dirname, `../lib/components/${fileName}.js`), - format: 'es', - exports: 'auto' - }, - plugins: [ - scss({ - output: `lib/css/${fileName}.css`, - prefix: '@import "./variable";', - processor: () => postcss([ - autoprefixer(), - postcssPresetEnv(), - postcssMinify(), - postcssImport() - ]), - sass: require('node-sass') - }), - ...commonRollupPlugins - ], - external: ['vue'] - }) - } - } - - return configList -} diff --git a/config/rollup.config.js b/config/rollup.config.js deleted file mode 100644 index f8ac641..0000000 --- a/config/rollup.config.js +++ /dev/null @@ -1,81 +0,0 @@ -import path from 'path' -import { nodeResolve } from '@rollup/plugin-node-resolve' -import commonjs from '@rollup/plugin-commonjs' -import esbuild from 'rollup-plugin-esbuild' -import vuePlugin from 'rollup-plugin-vue' -import polyfill from 'rollup-plugin-polyfill-node' -import image from '@rollup/plugin-image' -import alias from '@rollup/plugin-alias' -import json from '@rollup/plugin-json' -import progress from 'rollup-plugin-progress' -import filesize from 'rollup-plugin-filesize' - -import bundleConfig from './rollup.bundle' -import componentsConfig from './rollup.components' -import examplesConfig from './rollup.dev' - -const isProduct = process.env.NODE_ENV === 'production' -const customResolver = nodeResolve({ - extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.vue'] -}) -const commonRollupPlugins = [ - alias({ - entries: [{ - find: '@', - replacement: path.resolve(__dirname, 'packages') - }], - customResolver - }), - commonjs({ - include: [ - 'node_modules/**', - 'node_modules/**/*', - 'lib/**/*' - ] - }), - json(), - polyfill(), - nodeResolve({ - jsnext: true, - main: true, - extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.vue'] - }), - image(), - vuePlugin({ - include: /\.vue$/, - target: 'browser' - }), - esbuild({ - include: /\.[jt]sx?$/, // default, inferred from `loaders` option - exclude: /node_modules/, // default - minify: isProduct, - target: 'esnext', - tsconfig: 'tsconfig.json', - loaders: { - '.js': 'jsx' - } - }), - progress(), - filesize() -] -export default function () { - // 本地开发环境 - - if (process.env.IS_SERVE) { - return [ - bundleConfig(commonRollupPlugins, isProduct), - examplesConfig(commonRollupPlugins, isProduct) - ] - } - // 打包生产 - - if (process.env.BUILD === 'components') { // 分组件打包 - return componentsConfig(commonRollupPlugins, isProduct) - } else if (process.env.BUILD === 'bundle') { // bundle包 - return bundleConfig(commonRollupPlugins, isProduct) - } - return [ // 全量打包 - bundleConfig(commonRollupPlugins, isProduct), - ...componentsConfig(commonRollupPlugins, isProduct) - ] -} diff --git a/config/rollup.dev.js b/config/rollup.dev.js deleted file mode 100644 index 7ac662f..0000000 --- a/config/rollup.dev.js +++ /dev/null @@ -1,55 +0,0 @@ - -import path from 'path' -import copy from 'rollup-plugin-copy' -import replace from 'rollup-plugin-replace' -import html from 'rollup-plugin-html2' -import postcss from 'rollup-plugin-postcss' -import autoprefixer from 'autoprefixer' -import postcssPresetEnv from 'postcss-preset-env' -import postcssMinify from 'postcss-minify' -import postcssImport from 'postcss-import' -import browserSync from 'rollup-plugin-browsersync' - -export default function (commonRollupPlugins) { - return { - input: path.resolve(__dirname, '../examples/main.ts'), - output: { - name: 'examplesBundle', - file: 'dist/bundle.js', - format: 'iife', - extend: true, - sourcemap: true - }, - plugins: [ - ...commonRollupPlugins, - replace({ - 'process.env.NODE_ENV': JSON.stringify('development'), - 'process.env.VUE_ENV': JSON.stringify('browser') - }), - postcss({ - plugins: [ - autoprefixer(), - postcssPresetEnv(), - postcssMinify(), - postcssImport() - ] - }), - copy({ - targets: [{ - src: path.resolve(__dirname, '../lib/fonts/*'), - dest: path.resolve(__dirname, '../dist/fonts') - }] - }), - html({ - template: 'examples/index.html', - fileName: 'index.html' - }), - browserSync({ - server: { - baseDir: path.resolve(__dirname, '../dist') - }, - port: 8888 - }) - ] - } -} diff --git a/esbuild.config.js b/esbuild.config.js new file mode 100644 index 0000000..f03027f --- /dev/null +++ b/esbuild.config.js @@ -0,0 +1,155 @@ +import { build } from 'esbuild' +import vue from 'esbuild-plugin-vue' +import { sassPlugin } from 'esbuild-sass-plugin' +import progress from 'esbuild-plugin-progress' +import { esbuildPluginFileSize } from 'esbuild-plugin-filesize' +import postcss from 'postcss' +import autoprefixer from 'autoprefixer' +import postcssPresetEnv from 'postcss-preset-env' +import postcssImport from 'postcss-import' +import browserSync from 'browser-sync' +import components from './components.js' + +// 判断当前环境 +const isServe = process.argv.includes('serve') +// 包名 +const libraryName = 'fa-ui.js' + +// 封装esbuild本地服务插件 +function servePlugin (serveOptions = {}) { + // 创建服务实例 + const bs = browserSync.create('dev-server') + + return { + name: 'devServer', + setup (build) { + build.onEnd(() => { + // 避免重复启动服务 + if (!bs.active) { + // 初始化服务 + bs.init({ + port: 3000, + watch: true, + open: true, + ...serveOptions + }) + } + }) + } + } +} + +// 打包组件库 +async function buildLibrary () { + await build({ + entryPoints: ['packages/index.ts'], + outfile: `lib/${libraryName}`, + bundle: true, + format: 'esm', + tsconfig: 'tsconfig.json', + treeShaking: true, + minify: true, + external: ['vue'], + loader: { + '.eot': 'file', + '.svg': 'file', + '.ttf': 'file', + '.woff': 'file' + }, + plugins: [ + sassPlugin({ + async transform (source) { + const { css } = await postcss([ + autoprefixer, + postcssPresetEnv(), + postcssImport() + ]).process(source, { from: undefined }) + return css + } + }), + vue(), + progress(), + esbuildPluginFileSize() + ] + }) + + await build({ + entryPoints: Object.values(components), + outdir: 'lib/components', + bundle: true, + format: 'esm', + tsconfig: 'tsconfig.json', + treeShaking: true, + minify: true, + external: ['vue'], + loader: { + '.eot': 'dataurl', + '.svg': 'dataurl', + '.ttf': 'dataurl', + '.woff': 'dataurl' + }, + plugins: [ + sassPlugin({ + async transform (source) { + const { css } = await postcss([ + autoprefixer, + postcssPresetEnv(), + postcssImport() + ]).process(source, { from: undefined }) + return css + } + }), + vue(), + progress() + ] + }) + +} + +// 打包预览页面 +function buildExamples () { + build({ + entryPoints: ['examples/main.ts'], + outdir: 'examples/static', + bundle: true, + tsconfig: 'tsconfig.json', + format: 'iife', + watch: true, + sourcemap: true, + loader: { + '.ts': 'ts', + '.eot': 'file', + '.svg': 'file', + '.ttf': 'file', + '.woff': 'file' + }, + plugins: [ + sassPlugin({ + async transform (source) { + const { css } = await postcss([ + autoprefixer, + postcssPresetEnv(), + postcssImport() + ]).process(source, { from: undefined }) + return css + } + }), + vue(), + progress(), + servePlugin({ + server: 'examples' + }) + ] + }) +} + +// 启动函数 +async function start () { + if (isServe) { + buildExamples() + } else { + buildLibrary() + } +} + +start() diff --git a/examples/App.vue b/examples/App.vue index c5952b3..96ebbbe 100644 --- a/examples/App.vue +++ b/examples/App.vue @@ -3,7 +3,7 @@ default - + text @@ -58,79 +58,108 @@
+ default + text + success + danger + info + primary
+ + + - + > + + + > + + + > + + + > + + + > + +
-