网站搜索

javascript - Vue.js/TypeScript 单文件组件库,可扩展并编译为 es5


我正在尝试创建一个使用 TypeScript 编写的 Vue SFC 组件库,以便在其他项目中只需安装它并在 SFC 中使用语法 “import {component} from ..” 导入即可,而不需要 Vue.use()。我更希望它能编译成 es5,包含类型声明,并且尽可能具有可扩展性(它可能包含超过 100 个组件,我不想要一个单一的打包文件)。我尝试过不同的方法:webpack、vue-cli 3、vue-sfc-rollup 和 rollup,而最后一种似乎最接近我希望的结果。最终的包结构如下:

dist/
|__@types/
|  |__SampleComponent/
|  |  |__SampleComponent.vue.d.ts
|  |__index.d.ts
|
|__node_modules/
|  |__vue-runtime-helpers/ (contains normalize-component.mjs.js)
|
|__src/
   |__SampleComponent/
   |  |__SampleComponent.vue.js
   |  |__SampleComponent.vue_rollup-plugin-vue=script.js
   |__index.js (wrapper file)

问题是,正如我所说,.js 文件不是编译成 es5 而是 cjs(rollup 不能),组件的 .js 被拆分成两个文件,我不能放在 node-modules 文件夹外,看起来需要 normalize-component。这是我的配置文件:

rollup.config.js

import vue from "rollup-plugin-vue"
import typescript from "rollup-plugin-typescript2"
import renameExtensions from "@betit/rollup-plugin-rename-extensions"
import cleaner from "rollup-plugin-cleaner"
import commonjs from "rollup-plugin-commonjs"
import resolve from '@rollup/plugin-node-resolve';
// import del from 'rollup-plugin-delete'
import css from 'rollup-plugin-css-porter';
import sass from 'rollup-plugin-sass';
// import {terser} from "rollup-plugin-terser";

export default {
    input: "./src/index.ts",
    output: {
        format: "cjs", // This is what tells rollup to use ES6 modules
        dir: "dist",
        sourcemap: true
    },
    external: ["vue", "vue-class-component", "vue-property-decorator", "tslib", "vue-runtime-helpers"],
    plugins: [
        cleaner({targets: ["dist"]}),
        resolve(),
        // This extension renames all .vue and .ts to .js
        // (and updates the imports)
        renameExtensions({
            include: ["**/*.ts", "**/*.vue"],
            mappings: {".vue": ".vue.js", ".ts": ".js"}
        }),
        vue({
            css: true, // Dynamically inject css as a <style> tag
            compileTemplate: true, // Explicitly convert template to render function
        }),
        typescript({
            clean: true,
            useTsconfigDeclarationDir: true
        }),
        commonjs(),
        sass(),
        css(),
        /*terser({
            output: {
                ecma: 5,
            },
        }),*/ // minifies generated bundles

        /*del({
            targets: 'dist/index.d.ts',
            hook: 'generateBundle'
        })*/
    ],
    // Prevents bundling, but doesn't rename files
    preserveModules: true
}

package.json

import vue from "rollup-plugin-vue"
import typescript from "rollup-plugin-typescript2"
import renameExtensions from "@betit/rollup-plugin-rename-extensions"
import cleaner from "rollup-plugin-cleaner"
import commonjs from "rollup-plugin-commonjs"
import resolve from '@rollup/plugin-node-resolve';
// import del from 'rollup-plugin-delete'
import css from 'rollup-plugin-css-porter';
import sass from 'rollup-plugin-sass';
// import {terser} from "rollup-plugin-terser";

export default {
    input: "./src/index.ts",
    output: {
        format: "cjs",
        dir: "dist",
        sourcemap: true
    },
    external: ["vue", "vue-class-component", "vue-property-decorator", "tslib", "vue-runtime-helpers"],
    plugins: [
        cleaner({targets: ["dist"]}),
        resolve(),
        // This extension renames all .vue and .ts to .js
        // (and updates the imports)
        renameExtensions({
            include: ["**/*.ts", "**/*.vue"],
            mappings: {".vue": ".vue.js", ".ts": ".js"}
        }),
        vue({
            css: true, // Dynamically inject css as a <style> tag
            compileTemplate: true, // Explicitly convert template to render function
        }),
        typescript({
            clean: true,
            useTsconfigDeclarationDir: true
        }),
        commonjs(),
        sass(),
        css(),
        /*terser({
            output: {
                ecma: 5,
            },
        }),*/ // minifies generated bundles

        /*del({
            targets: 'dist/index.d.ts',
            hook: 'generateBundle'
        })*/
    ],
    // Prevents bundling, but doesn't rename files
    preserveModules: true
}

tsconfig.json

{
  "compilerOptions": {
    "module": "ES2015",
    "target": "es5",
    "downlevelIteration": true,
    "resolveJsonModule": true,
    "importHelpers": true,
    "moduleResolution": "node",
    "sourceMap": true,
//    "outFile": "out.js",
    "declaration": true,
    "outDir": "./dist/lib",
    "declarationDir": "./dist/@types",
    "strict": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "types": [
      "node"
    ],
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ],
    "plugins": [
      {
        "name": "typescript-tslint-plugin"
      }
    ]
  },
  "include": [
    // Source
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    // Tests
    "tests/**/*.ts",
    "tests/**/*.tsx",
    "src/browser/**/*.ts",
    "src/site/images/typings.d.ts",
    "src/site/images"
  ],
  "exclude": [
    "node_modules"
  ],
  "files": [
    "src/shims-vue.d.ts"
  ]
}

如果我的解释不够清楚,或者我的配置很混乱,提前表示抱歉。谢谢