Search code examples
typescriptvue.jsrollupjsvue-property-decorator

Vue + Typescript + rollup


I'm trying to rollup Vue component lib, written on the typescript + vue-property-decorator. I have several Vue components, and plugin class in a separated file, where the components are imported:

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

The test suite (vue-cli + jest) working fine, all tests passing, but on the build stage with rollup module path resolution working incorrect, since the code of the components not present in the final build.

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 <[email protected]>",
    "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 <[email protected]>"
    ],
    "keywords": [
        "vue",
        "form",
        "forms",
        "validation",
        "validate"
    ],
    "license": "MIT",
    "publishConfig": {
        "access": "public"
    },
    "repository": {
        "type": "git",
        "url": "git+ssh://[email protected]/retailcrm/vue-formulario.git"
    }
}

Caught on the console:

(!) 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)

Trying to find out an appropriate solution.

Full code placed here: https://github.com/cmath10/vue-formulario


Solution

  • That tsconfig contains paths affects only how TypeScript compiler resolves modules but doesn't replace aliased import paths in JS output. It's possible for tools to transparently process files with a respect to paths option but this shouldn't be expected.

    Module aliasing for the bundle can be addressed by another Rollup plugin like @rollup/plugin-alias. This reveals the problem with the latest @rollup/plugin-typescript that results in processing errors when it's used with other plugins.

    A way to make this setup workable is to switch to another TypeScript plugin, 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: './$1' }] }),
        commonjs(),
        autoExternal(),
        buble({ objectAssign: 'Object.assign' }),
        terser(),
    ]
    

    There may be no need for Buble plugin because TypeScript is able to handle ES5 transpilation.