A Roadmap
  • Introduction
  • Roadmap
  • Basics
    • Basic Terminal Usage
      • Shell
        • 基本
        • 变量
        • 传递参数
        • 运算符
        • 命令
        • 流程控制
        • 函数
        • 输入输出重定向
    • Character Encoding
      • 字符编码
    • Data Structures & algorithms
    • Network
      • TCP/IP
      • Http/Https
        • 浏览器缓存
        • Status Code
        • GET & POST
        • HTTPS 握手过程
        • HostOnly Cookie
      • CDN
        • CDN 工作原理
    • Version Control
      • git message format
      • git commands
    • Principles
    • Design Patterns
    • Others
      • JSON
      • 正则表达式
  • Front End
    • Web Standard
      • Html
      • CSS
        • font-face 小记
        • Grid 布局简易笔记
      • Javascript
        • Ajax
          • Fetch
          • XMLHttpRequest
        • DOM
          • Selection
          • 常用 DOM 操作
          • script 标签的几个属性
        • Ecmascript
          • this 关键字
          • Event Loop
          • 隐式转换
          • Date
        • Event
          • 模拟事件
          • Others
    • Development
      • Package Management
        • npm
      • Modulization
        • 模块化机制
        • webpack 打包解析
      • Architecture
      • Build Tools
        • 如何编写一个自定义的 eslint 规则?
      • Debug
        • 移动端调试 web
      • Pre/Post Processors
      • Test
        • Jest Snapshot 使用指南
      • Type Checkers
        • TS 中 enum 的编译结果
    • Libs & frameworks
    • Platforms
      • Browser
        • Basics
          • 从输入 URL 到页面加载完成都发生了什么事情?
          • HTML 加载的过程示意图
          • 为什么读取某些属性,也会导致回流?
          • Chrome 进程模型
        • PWA
        • Compatible
        • Cross Origin
        • Performance
          • 性能检测:performance 对象
          • 性能指标
        • Others
          • 移动端 web 开发笔记
      • Server
      • Desktop Applications
      • Mobile Applications
        • Flutter 在移动端和 Web 端的技术实现
  • Back End
    • outline
    • Languages
      • Node
        • Event Loop
        • NodeJS 中的进程与线程
        • NodeJS 中的 esModule 与 commonJS
  • Clients
    • outline
    • 安装 IPA 包
  • DevOps
    • Languages
    • OS Concepts
    • Servers & terminal
  • UI & UX
    • outline
  • Others
    • Posts
      • 使用 node 爬取数据并导出到 excel
      • antd 1.x datepicker 时区问题
      • babel-transform-runtime 踩坑记录
      • lodash 按需加载注意事项
      • 记一次项目迁移的踩坑记录
      • 时区与JS中的Date对象
      • 记一次 vue + ts 开发踩坑
    • Tools
      • 个人常用的工具分享
      • tmux 简要笔记
Powered by GitBook
On this page
  • 项目代码
  • 别在webpack中混用import和module.exports

Was this helpful?

  1. Others
  2. Posts

babel-transform-runtime 踩坑记录

Previousantd 1.x datepicker 时区问题Nextlodash 按需加载注意事项

Last updated 3 years ago

Was this helpful?

起因是这样的,我在pikachu项目下新建了一个libs文件夹,使用module.exports导出模块。并且在同级的pc和mobile项目下使用npm-link的方式引入了libs模块,在代码中使用es Modules的import引用了该模块,结果PC项目编译正常,mobile项目编译出错。

项目代码

libs/index.js

pc/a.js

mobile/b.js

别在webpack中混用import和module.exports

添加完代码之后,PC项目运转良好,指标正常,但是mobile项目编译直接抛出异常:

肯定有人会问,上面libs/index.js中的代码并没有任何地方使用了import呀。这是一个好问题,我们需要深入到.babelrc中看一看:

pc/.babelrc (这里面有个坑,大家可以找找茬)

mobile/.babelrc

虽然两个项目的babelrc配置有一些细节上的差异,但是mobile配置的env模式包括了pc的es2015 preset,所以两者没有特别大的差异。

tranform-runtime的转换如图所示。

回到问题本身,因为libs/index.js中使用了Object.create方法,transform-runtime会对这个方法进行polyfill,导致该文件混用了import 和 module.exports

合理使用transform-es2015-modules-commonjs 前面已经说到,导致mobile端报错是因为混用了import 和 module.exports两种写法,但是为什么PC没有报错呢? 仔细看下PC和mobile的babelrc,可以发现pc的babelrc配置有一处错误

pc/.babelrc

mobile/.babelrc

ES2015 modules to CommonJS transform

This plugin transforms ES2015 modules to CommonJS

// input
export default 42;

// output
Object.defineProperty(exports, "__esModule", {
  value: true});
exports.default = 42;

官方的解释是,该插件用于将代码中的es Modules写法转化为commonJS写法。与之类似,babel还提供了一下几个插件,支持transform es Modules的写法:

PC的babelrc配置中错误的把modules写成了module,导致PC的babel编译时会将所有的es Module转化为commonJS的写法。 而mobile项目中的配置要求不转化es Modules,于是babel-transform-plugin引入polyfill时采用的import写法就和libs/index.js中的module.exports写法混用了,导致编译失败。

要避免上述问题,直接删掉modules配置项即可。当然也可以修改为其他的模块语法,比如"umd"。

熟悉webpack打包原理的同学都知道,上图报错是因为,webpack不支持在同一个文件中使用Import和module.exports。关于混用这两种方式的讨论,可以查看该issue Cannot assign to read only property 'exports' of object '#\' (mix require and export) 如果想了解webpack处理模块引入的基本工作原理,可以参考,这里不展开说明。

另外可以发现,两个项目都使用了babel-transform-runtime这个plugin。为什么要提到这个插件呢?使用babel比较多的同学肯定知道,babel可以通过或来对代码进行transform/compile。而transform-runtime在实际使用过程中,引入polyfill时会使用es Modules import的方式,关于这个行为的细节可以参考

这个modules参数是个什么东西呢? 在babel的es2015 presets中包含了一个叫做的plugin。

而在直接使用es2015或者env的作为presets时,可以通过 这个参数来控制是否transform es Modules,默认使用commonJS的形式,如果传入false则不启用。

import、require、export、module.exports 混合使用详解
babel-polyfill
babel-transform-runtime
babel-transform-runtime adds import in modules that don't use es6
transform-es2015-modules-commonjs
es2015-modules-amd
es2015-modules-commonjs
es2015-modules-systemjs
es2015-modules-umd
modules