rollup react 常见问题解决大法(转载)

(转载) Marvin's Blog【程式人生】

原文链接:https://marvinsblog.net/

Ability will never catch up with the demand for it

23Dec 2018

用Rollup打包Typescript和React

前端项目最麻烦的问题是如何解决代码间的依赖,以及如果打包代码。目前比较主流的代码打包工具有webpack和rollup。我比较喜欢后者,因为配置比较简单,而且一上来就支持es6.

我的需求是要把react和typescript打包到一起。react提供了一个工具Create React App,可以帮助你快速搭建一个react app项目。但是Create React App默认支持的是webpack,而不是我希望的rollup。所以本文研究如何用rollup来打包react和typescript。

实验过程

创建项目

首先创建一个项目demo,并添加react相关的依赖(react,react-dom):

mkdir demo
cd demo
yarn add react react-dom

上面的命令会在当前目录生成node_modules package.json yarn.lock

添加typescript

然后添加typescript到dev依赖中

yarn add --dev typescript

创建里面tsconfig.json文件,用来配置typescript,内容如下:

{
  "compilerOptions": {
    "target": "es6",
    "jsx": "react",
    "sourceMap": true,
    "module": "commonjs"
  },
  "exclude": [
    "node_modules"
  ]
}

上面的配置让typescript能够转译tsx文件(也就是ts版的jsx文件),并生成es6代码。

demo.tsx

现在来编写一个小例子demo.tsx,内容如下:

import * as React from "react";
import * as ReactDOM from "react-dom";

ReactDOM.render(
  <div>
  <h1>Hello, Welcome to the first page</h1>
  </div>,
  document.getElementById("root")
);

可以使用./node_modules/.bin/tsc -b命令来编译上面的例子,会生成demo.js,其内容如下:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const React = require("react");
const ReactDOM = require("react-dom");
ReactDOM.render(React.createElement("div", null,
    React.createElement("h1", null, "Hello, Welcome to the first page")), document.getElementById("root"));
//# sourceMappingURL=demo.js.map

添加rollup

下面的命令在dev依赖中添加rollup以及rollup的两个plugin:rollup-plugin-commonjs和rollup-plugin-node-resolve

yarn add --dev rollup rollup rollup-plugin-commonjs rollup-plugin-node-resolve

我们还需要添加rollup的typescript相关的plugin

yarn add --dev rollup-plugin-typescript tslib

添加tslib,是因为它是rollup-plugin-typescript的peer依赖

创建rollup的配置文件rollup.config.js,添加以下内容

import typescript from 'rollup-plugin-typescript'
import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'

export default {
  input: './demo.tsx',
  output: {
    file: 'dist/index.js',
    format: 'iife',
    exports: 'named',
    sourcemap: true
  },
  plugins: [
    typescript(),
    resolve(),
    commonjs()
  ]
}

Missing exports错误

使用./node_modules/.bin/rollup -c来打包当前项目,不料却出现若干问题:

./demo.tsx → dist/index.js...
(!) Missing exports
https://rollupjs.org/guide/en#error-name-is-not-exported-by-module-
demo.tsx
render is not exported by node_modules/react-dom/index.js
...
createElement is not exported by node_modules/react/index.js
...
createElement is not exported by node_modules/react/index.js
...

解决办法一

一个解决办法是使用rollup-plugin-commonjs的custom-named-exports功能,这需要修改rollup.config.js的plugin配置中的commonjs部分:

    commonjs({
      namedExports: {
        'node_modules/react/index.js': ['createElement'],
        'node_modules/react-dom/index.js': ['render']
      }
    })

做完上述的配置后执行./node_modules/.bin/rollup -c,错误消除。

这个解题思路和StackOverflow的这个帖子一致

解决办法二

另一个解决办法,在Making of a component library for React一文中提到的,是在rollup.confg.js中把react和react-dom作为外部依赖。

修改rollup.config.js:

export default {
  input: './demo.tsx',
  output: {
    file: 'dist/index.js',
    format: 'iife',
    exports: 'named',
    sourcemap: true,
    // 添加globals
    globals: {
      react: 'React',
      'react-dom': 'ReactDOM'
    }
  },
  // 添加externs
  external: ['react', 'react-dom'],
  plugins: [
    typescript(),
    resolve(),
    // 取消之前对commonjs的配置
    commonjs()
  ]
}

这样做的好处是./node_modules/.bin/rollup -c执行非常快,因为不需要打包react和react-dom;坏处是需要自己在html中添加react和react-dom,例如:

<!-- react和react-dom 需要在你的脚本之前添加 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

上面的例子参考了react-rectangle-popup-menu

解决办法三

解决办法三和解决办法二相似,但是使用到了peer依赖。这个解决办法来自于create-react-library。它可以用来创建基于rollup和typescript的react库。

create-react-library把react和react-dom在package.json中列为了peerDependencies(在yarn add的时候指定–peer即可)。然后使用rollup-plugin-peer-deps-external插件,这个插件可以把让rollup把所有的peerDependencies当成external依赖处理。最后的效果跟解决办法二类似

解决办法四

如果我们在demo.tsx里面把下面的代码:

import * as React from "react";
import * as ReactDOM from "react-dom";

改成

import React from "react";
import ReactDOM from "react-dom";

那么错误有可能变成:

[!] Error: 'default' is not exported by node_modules/react-dom/index.js

有一个小戏法能够帮助解决这个问题,那就是在rollup.config.js中使用rollup-plugin-replace插件:

import replace from 'rollup-plugin-replace'
...
export default {
...
  plugins: [
    replace({ 'process.env.NODE_ENV': JSON.stringify('devolpment') }), // 或者production
...

在nodejs中把环境变量process.env.NODE_ENV改成development或者production,这个错误就会消失,实在不知道是为什么呢? buble-react-rollup-starter也是这样��做的。

其他参考

typescript和reactjs相关

rollup相关

nodejs依赖

JS模块

打包器

其他starter

Categories

frontend programming

Tags

reactjs rollupjs typescript

comments powered by Disqus

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349