#はじめに
最近はreactアプリを作るときは必ずcreate-react-app
を使うのですが、正直言って組み込みの react-script build
で生成されたものって納品しにくいんですよね。widget
タイプのものを作成した場合は特にそう思います。パフォーマンスの最適化や、ソースコードのサイズも気になるところでして。
で、公式は何て言っているのかなーと思って覗いてみると、brunch
やbrowserfy
なんかの他に rollup
があるのを発見。遅ればせながらこんなツールがあるのを知りました。
ところが、以下のサイトや、公式の薦める情報を参考にしたんですが、中々思うように動作しません。
色々試行錯誤の末、動作が確認出来ましたので公開します。
#前提
create-react-app v3.0.1
react v16.8.6
#設定方法
##始めに
アプリを作ります。
$ create-react-app sample
$ cd sample
##rollupのインストール
本体とプラグインもろとも一緒に
$ yarn add --dev rollup \
rollup-plugin-commonjs \
rollup-plugin-replace \
rollup-plugin-babel \
rollup-plugin-uglify-es \
rollup-plugin-css-porter \
rollup-plugin-svg \
rollup-plugin-node-resolve
##rollup.config.jsの設定
プロジェクトフォルダ直下に記述します。
import replace from 'rollup-plugin-replace';
import babel from 'rollup-plugin-babel';
import css from 'rollup-plugin-css-porter';
import svg from 'rollup-plugin-svg';
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify-es';
const env = process.env.NODE_ENV;
export default {
input: 'src/index.js',
output: {
file: 'build/js/bundle.js',
format: 'iife',
},
plugins: [
replace({ 'process.env.NODE_ENV': JSON.stringify(env) }),
babel({
exclude: ['node_modules/**'],
presets: ['@babel/env', '@babel/preset-react'],
}),
css({ dest: 'build/css/bundle.css', raw: false, minified: true }),
svg({ base64: true }),
nodeResolve({ browser: true }),
commonjs(),
env === 'production' && uglify(),
],
};
プラウザアプリの場合は format:'iife'
で問題無いですが、Node.js
で動かす場合にはまた別のフォーマットになります。
output:{file:[path]}
, plugins:{css:{dest:[path]}}
でjs
とcss
それぞれの出力先を変更します。
各plugin
の記述順序は重要です。特に babel()
とcommonjs()
の記述順序を入れ変えると動作しません。
##package.jsonの修正
pakage.json の "build": "react-script build",
を以下のように修正します。
"scripts": {
"build": "export NODE_ENV=production && rollup -c",
},
##ビルド実行
$ yarn build
成功すると build/css/bundle.min.css
bundle/js/bundle.js
が生成されていますので、htmlに組み込んで下さい。
#htmlも自動作成
js
やcss
のアウトプット時に パラメーター[hash]
を指定すると内容をハッシュ化した値がファイル名に追記されるようになります。また、そういった場合はhtmlも自動生成したいですよね。
パッケージ rollup-plugin-bundle-html
を追加して、テンプレートファイルを作成します。
[hash]
値が追記されてファイルが作成されるようになると、一度build
内を消去しないと偉いことになりますので rollup-plugin-cleaner
も入れておきます。
$ yarn add --dev rollup-plugin-bundle-html rollup-plugin-cleaner
テンプレートファイルを作成します。(例:public/index.html
を参考に)
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
roolup.config.jsを修正します。
//...
import html from 'rollup-plugin-bundle-html';
import cleaner from 'rollup-plugin-cleaner';
//...
export default {
input: 'src/index.js',
output: {
file: 'build/js/bundle-[hash].js',
format: 'iife',
},
plugins: [
cleaner({
targets: ['build/js/', 'build/css/'],
}),
//...
css({ dest: 'build/css/bundle-[hash].css', raw: false, minified: true }),
//...
html({
template: 'template/index.html',
dest: 'build',
filename: 'index.html',
inject: 'body',
}),
],
};
ビルドすると build/index.html
が生成されます。以下のような感じになります。
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000">
<title>React App</title>
<link rel="stylesheet" href="css/bundle-788e2801d0a5197580d3d834ccb87a8a.min.css">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="js/bundle-d6579d4e543ab201447a819af62c3a76.js"></script>
</body>
</html>
#名前付きexportについて
いろんなモジュールを追加してプログラムを作成していくとbuild
に失敗することがあります。
たとえば以下のようなエラーが出ます。名前付きのexportを解釈できない場合があるようです。
[!] Error: 'createFactory' is not exported by node_modules/react/index.js
https://rollupjs.org/guide/en#error-name-is-not-exported-by-module-
node_modules/recompose/dist/Recompose.esm.js (1:16)
1: import React, { createFactory, Component, createElement } from 'react';
こういった場合はcommonjs()
プラグインに以下のような記述をして回避して下さい。
plugins: [
commonjs({
namedExports: {
'node_modules/react/index.js': [
'createFactory',
'Component',
'createElement',
],
},
}),
]
#その他エラー時
調子こいてステートレス関数なんか書いていくとコンパイルエラーになります。そういうときはエラーメッセージをよく読むと対応方法が書いてありますので確認してみて下さい。
自分の場合は @babel/plugin-proposal-class-properties
を追加しました。
/*...*/
babel({
exclude: ['node_modules/**'],
presets: ['@babel/env', '@babel/preset-react'],
plugins: ['@babel/plugin-proposal-class-properties'],
}),
/*...*/
#修正履歴
- 2019/07/10 使用モジュールを
rollup-plugin-uglify
からrollup-plugin-gulify-es
に変更 - 2019/07/10 「その他」セクションを追加