Vue + 打字稿 + 汇总

Vue + Typescript + rollup

我正在尝试汇总 Vue 组件库,它是在 typescript + vue-属性-decorator 上编写的。我有几个 Vue 组件,插件 class 在一个单独的文件中,组件导入的位置:

import FormularioForm from '@/FormularioForm.vue'
import FormularioInput from '@/FormularioInput.vue'
import FormularioGrouping from '@/FormularioGrouping.vue'

测试套件 (vue-cli + jest) 工作正常,所有测试都通过了,但是在构建阶段,汇总模块路径解析工作不正确,因为组件的代码不存在于最终构建中。

rollup.config:

import autoExternal from 'rollup-plugin-auto-external'
import buble from '@rollup/plugin-buble'
import commonjs from '@rollup/plugin-commonjs'
import { terser } from 'rollup-plugin-terser'
import typescript from '@rollup/plugin-typescript'
import vue from 'rollup-plugin-vue'

export default {
    input: 'src/index.ts',
    output: [{
        name: 'Formulario',
        exports: 'default',
        globals: {
            'is-plain-object': 'isPlainObject',
            'is-url': 'isUrl',
            'nanoid/non-secure': 'nanoid',
        },
        sourcemap: false,
    }],
    external: ['nanoid/non-secure'],
    plugins: [
        commonjs(),
        autoExternal(),
        typescript({ sourceMap: false }),
        vue({
            css: true,
            compileTemplate: true
        }),
        buble({
            objectAssign: 'Object.assign',
        }),
        terser(),
    ]
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.js",
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

package.json

{
    "name": "@retailcrm/vue-formulario",
    "version": "0.1.0",
    "author": "RetailDriverLLC <integration@retailcrm.ru>",
    "scripts": {
        "build": "npm run build:esm & npm run build:umd & npm run build:iife & wait && echo \"Build complete:\nesm: $(gzip -c dist/formulario.esm.js | wc -c)b gzip\numd: $(gzip -c dist/formulario.umd.js | wc -c)b gzip\nmin: $(gzip -c dist/formulario.min.js | wc -c)b gzip\"",
        "test": "NODE_ENV=test jest --config test/jest.conf.js",
        "build:esm": "rollup --config build/rollup.config.js --format es --file dist/formulario.esm.js",
        "build:iife": "rollup --config build/rollup.iife.config.js --format iife --file dist/formulario.min.js",
        "build:size": "gzip -c dist/formulario.esm.js | wc -c",
        "build:umd": "rollup --config build/rollup.config.js --format umd --file dist/formulario.umd.js",
        "dev": "vue-cli-service serve --port=7872 examples/main.js",
        "test:coverage": "NODE_ENV=test jest --config test/jest.conf.js --coverage",
        "test:watch": "NODE_ENV=test jest --config test/jest.conf.js --watch"
    },
    "main": "dist/formulario.umd.js",
    "module": "dist/formulario.esm.js",
    "browser": {
        "./sfc": "src/index.ts"
    },
    "unpkg": "dist/formulario.min.js",
    "dependencies": {
        "is-plain-object": "^3.0.0",
        "is-url": "^1.2.4",
        "nanoid": "^2.1.11",
        "vue-class-component": "^7.2.3",
        "vue-i18n": "^8.17.7",
        "vue-property-decorator": "^8.4.2"
    },
    "devDependencies": {
        "@babel/core": "^7.9.6",
        "@babel/plugin-transform-modules-commonjs": "^7.9.6",
        "@babel/preset-env": "^7.9.6",
        "@rollup/plugin-alias": "^3.1.1",
        "@rollup/plugin-buble": "^0.21.3",
        "@rollup/plugin-commonjs": "^11.1.0",
        "@rollup/plugin-node-resolve": "^7.1.3",
        "@rollup/plugin-typescript": "^6.0.0",
        "@types/is-url": "^1.2.28",
        "@types/jest": "^26.0.14",
        "@types/nanoid": "^2.1.0",
        "@typescript-eslint/eslint-plugin": "^2.26.0",
        "@typescript-eslint/parser": "^2.26.0",
        "@vue/cli-plugin-babel": "^4.3.1",
        "@vue/cli-plugin-eslint": "^4.3.1",
        "@vue/cli-plugin-typescript": "^4.5.7",
        "@vue/cli-service": "^4.5.4",
        "@vue/component-compiler-utils": "^3.1.2",
        "@vue/eslint-config-standard": "^5.1.2",
        "@vue/eslint-config-typescript": "^5.0.2",
        "@vue/test-utils": "^1.0.2",
        "autoprefixer": "^9.7.6",
        "babel-core": "^7.0.0-bridge.0",
        "babel-eslint": "^10.1.0",
        "babel-jest": "^25.5.1",
        "eslint": "^5.16.0",
        "eslint-config-standard": "^12.0.0",
        "eslint-plugin-import": "^2.20.1",
        "eslint-plugin-node": "^8.0.1",
        "eslint-plugin-promise": "^4.1.1",
        "eslint-plugin-standard": "^4.0.0",
        "eslint-plugin-vue": "^5.2.3",
        "flush-promises": "^1.0.2",
        "jest": "^26.5.2",
        "jest-vue-preprocessor": "^1.7.1",
        "rollup": "^1.32.1",
        "rollup-plugin-auto-external": "^2.0.0",
        "rollup-plugin-internal": "^1.0.4",
        "rollup-plugin-multi-input": "^1.1.1",
        "rollup-plugin-terser": "^5.3.0",
        "rollup-plugin-vue": "^5.1.7",
        "ts-jest": "^26.4.1",
        "typescript": "~3.9.3",
        "vue": "^2.6.11",
        "vue-jest": "^3.0.5",
        "vue-runtime-helpers": "^1.1.2",
        "vue-template-compiler": "^2.6.11",
        "vue-template-es2015-compiler": "^1.9.1",
        "watch": "^1.0.2"
    },
    "bugs": {
        "url": "https://github.com/retailcrm/vue-formulario/issues"
    },
    "contributors": [
        "Justin Schroeder <justin@wearebraid.com>"
    ],
    "keywords": [
        "vue",
        "form",
        "forms",
        "validation",
        "validate"
    ],
    "license": "MIT",
    "publishConfig": {
        "access": "public"
    },
    "repository": {
        "type": "git",
        "url": "git+ssh://git@github.com/retailcrm/vue-formulario.git"
    }
}

在控制台上捕获:

(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
@/FormularioForm.vue (imported by src/Formulario.ts)
@/FormularioInput.vue (imported by src/Formulario.ts)
@/FormularioGrouping.vue (imported by src/Formulario.ts)

正在尝试找出合适的解决方案。

完整代码放在这里:https://github.com/cmath10/vue-formulario

tsconfig 包含 paths 仅影响 TypeScript 编译器解析模块的方式,但不会替换 JS 输出中的别名导入路径。工具可以根据 paths 选项透明地处理文件,但这不应该是预期的。

bundle 的模块别名可以通过另一个 Rollup 插件解决,例如 @rollup/plugin-alias。这揭示了最新 @rollup/plugin-typescript 与其他插件一起使用时导致处理错误的问题。

使此设置可行的一种方法是切换到另一个 TypeScript 插件,rollup-plugin-typescript2:

import alias from '@rollup/plugin-alias';
import typescript from 'rollup-plugin-typescript2'    
...
plugins: [
    typescript({
         check: false // disable typechecks if necessary
    }),
    vue({ css: true, compileTemplate: true }),
    alias({ entries: [{ find:/^@\/(.+)/, replacement: './' }] }),
    commonjs(),
    autoExternal(),
    buble({ objectAssign: 'Object.assign' }),
    terser(),
]

可能不需要 Buble 插件,因为 TypeScript 能够处理 ES5 转译。