Vue-cli: 库模式打包文件在webpack中不可用

Created on 18 Apr 2019  ·  2Comments  ·  Source: vuejs/vue-cli

Version

3.6.0

Environment info

System:
    OS: macOS 10.14.3
    CPU: (8) x64 Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
  Binaries:
    Node: 11.11.0 - ~/.nvm/versions/node/v11.11.0/bin/node
    Yarn: 1.13.0 - /usr/local/bin/yarn
    npm: 6.7.0 - ~/.nvm/versions/node/v11.11.0/bin/npm
  Browsers:
    Chrome: 73.0.3683.103
    Firefox: 65.0
    Safari: 12.0.3
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.0.0-beta.3 
    @vue/babel-plugin-transform-vue-jsx:  1.0.0-beta.3 
    @vue/babel-preset-app:  3.6.0 
    @vue/babel-preset-jsx:  1.0.0-beta.3 
    @vue/babel-sugar-functional-vue:  1.0.0-beta.3 
    @vue/babel-sugar-inject-h:  1.0.0-beta.3 
    @vue/babel-sugar-v-model:  1.0.0-beta.3 
    @vue/babel-sugar-v-on:  1.0.0-beta.3 
    @vue/cli-overlay:  3.6.0 
    @vue/cli-plugin-babel: ^3.6.0 => 3.6.0 
    @vue/cli-plugin-eslint: ^3.6.0 => 3.6.0 
    @vue/cli-plugin-pwa: ^3.6.0 => 3.6.0 
    @vue/cli-plugin-unit-jest: ^3.6.0 => 3.6.3 
    @vue/cli-service: ^3.6.0 => 3.6.0 
    @vue/cli-shared-utils:  3.6.0 
    @vue/component-compiler-utils:  2.6.0 
    @vue/eslint-config-standard: ^4.0.0 => 4.0.0 
    @vue/preload-webpack-plugin:  1.1.0 
    @vue/test-utils: 1.0.0-beta.29 => 1.0.0-beta.29 
    @vue/web-component-wrapper:  1.2.0 
    eslint-plugin-vue: ^5.0.0 => 5.2.2 
    jest-serializer-vue:  2.0.2 
    vue: ^2.6.10 => 2.6.10 
    vue-eslint-parser:  2.0.3 
    vue-hot-reload-api:  2.3.3 
    vue-jest:  3.0.4 
    vue-loader:  15.7.0 
    vue-router: ^3.0.3 => 3.0.6 
    vue-style-loader:  4.1.2 
    vue-template-compiler: ^2.5.21 => 2.6.10 
    vue-template-es2015-compiler:  1.9.1 
    vuex: ^3.0.1 => 3.1.0 
  npmGlobalPackages:
    @vue/cli: 3.5.4

Steps to reproduce

使用了vue-cli安装了初始化了一个示例仓库,在src文件夹内创建了两个文件
image
image

通过vue-cli-service 进行库文件打包 npx vue-cli-service build --target lib --name mylib src/api.js

image

将dist/mylib.common.js 拷贝到src文件内

启动项目报错
image

What is expected?

能够正常引入打包后的资源文件

What is actually happening?

启动项目报错
image

Most helpful comment

下次麻烦不要把复现代码放在截图里……不然我们复现问题需要照着截图手打一遍,很浪费时间

这个问题解释起来略复杂……总的来说这个打包的结果不应该直接复制到项目里使用,一般应该是从 node_modules 里引用,这样就不会有问题


  • 这个报错的直接原因是 ES Module 中不能对 module.exports = 赋值
  • 所以问题是 mylib.common.js 被识别成了 ES Module
  • 之所以被识别,是因为其中有 import 语句
  • 这几个 import 语句是被 babel 带进来的(可以试试 npx babel src/mylib.common.js 看编译产物)

到这一步就可以确定解决方案了:让 babel 跳过这个文件的编译就行了。
可以在 babel.config.js 里加 ignore,也可以在 vue.config.js 里为 webpack 规则加 exclude
考虑到这只是 babel 的问题,所以这里拿 babel 配置举例:

// babel.config.js
module.exports = {
  presets: [
    '@vue/app'
  ],
  ignore: ['src/mylib.common.js']
}


之所以 babel 会引入这几个 import,原因有这几个

  • mylib.common.js 里有 typeof Symbol !== 'undefined' 这样的语句
  • https://babeljs.io/docs/en/babel-preset-env#usebuiltins 我们内部配置了这里的 useBuiltIns: usage,babel 会判断需要引入 Symbol polyfill(引入方式根据 modules 配置,可能是 require 一个模块也可能是 import 一个模块)
  • https://babeljs.io/docs/en/babel-preset-env#modules 我们内部配置了 modules: false,为了不让 babel 把 ES Module 转换成 commonjs 从而影响 webpack 的 tree shaking 能力
  • 由于前两个配置,所以 babel 会在文件开头加入 import "core-js/modules/es6.symbol"; 这样的语句

(另外 transform-runtime plugin 也有起作用,不过原理类似,这里就不细说了)


总结就是尽量不要在项目中混用 CommonJS 和 ES Module,背后的问题很复杂。

All 2 comments

下次麻烦不要把复现代码放在截图里……不然我们复现问题需要照着截图手打一遍,很浪费时间

这个问题解释起来略复杂……总的来说这个打包的结果不应该直接复制到项目里使用,一般应该是从 node_modules 里引用,这样就不会有问题


  • 这个报错的直接原因是 ES Module 中不能对 module.exports = 赋值
  • 所以问题是 mylib.common.js 被识别成了 ES Module
  • 之所以被识别,是因为其中有 import 语句
  • 这几个 import 语句是被 babel 带进来的(可以试试 npx babel src/mylib.common.js 看编译产物)

到这一步就可以确定解决方案了:让 babel 跳过这个文件的编译就行了。
可以在 babel.config.js 里加 ignore,也可以在 vue.config.js 里为 webpack 规则加 exclude
考虑到这只是 babel 的问题,所以这里拿 babel 配置举例:

// babel.config.js
module.exports = {
  presets: [
    '@vue/app'
  ],
  ignore: ['src/mylib.common.js']
}


之所以 babel 会引入这几个 import,原因有这几个

  • mylib.common.js 里有 typeof Symbol !== 'undefined' 这样的语句
  • https://babeljs.io/docs/en/babel-preset-env#usebuiltins 我们内部配置了这里的 useBuiltIns: usage,babel 会判断需要引入 Symbol polyfill(引入方式根据 modules 配置,可能是 require 一个模块也可能是 import 一个模块)
  • https://babeljs.io/docs/en/babel-preset-env#modules 我们内部配置了 modules: false,为了不让 babel 把 ES Module 转换成 commonjs 从而影响 webpack 的 tree shaking 能力
  • 由于前两个配置,所以 babel 会在文件开头加入 import "core-js/modules/es6.symbol"; 这样的语句

(另外 transform-runtime plugin 也有起作用,不过原理类似,这里就不细说了)


总结就是尽量不要在项目中混用 CommonJS 和 ES Module,背后的问题很复杂。

@sodatea 感谢

Was this page helpful?
0 / 5 - 0 ratings