LoginSignup
3
3

More than 3 years have passed since last update.

create-react-app で作成したコードをrollupで整形する

Last updated at Posted at 2019-06-28

はじめに

最近はreactアプリを作るときは必ずcreate-react-appを使うのですが、正直言って組み込みの react-script buildで生成されたものって納品しにくいんですよね。widgetタイプのものを作成した場合は特にそう思います。パフォーマンスの最適化や、ソースコードのサイズも気になるところでして。

で、公式は何て言っているのかなーと思って覗いてみるとbrunchbrowserfyなんかの他に 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の設定

プロジェクトフォルダ直下に記述します。

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]}}jscssそれぞれの出力先を変更します。

pluginの記述順序は重要です。特に babel()commonjs()の記述順序を入れ変えると動作しません。

package.jsonの修正

pakage.json の "build": "react-script build",
を以下のように修正します。

package.json
"scripts": {
  "build": "export NODE_ENV=production && rollup -c",
},

ビルド実行

$ yarn build

成功すると build/css/bundle.min.css bundle/js/bundle.jsが生成されていますので、htmlに組み込んで下さい。

htmlも自動作成

jscssのアウトプット時に パラメーター[hash]を指定すると内容をハッシュ化した値がファイル名に追記されるようになります。また、そういった場合はhtmlも自動生成したいですよね。

パッケージ rollup-plugin-bundle-htmlを追加して、テンプレートファイルを作成します。
[hash]値が追記されてファイルが作成されるようになると、一度build内を消去しないと偉いことになりますので rollup-plugin-cleanerも入れておきます。

$ yarn add --dev rollup-plugin-bundle-html rollup-plugin-cleaner

テンプレートファイルを作成します。(例:public/index.htmlを参考に)

template/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を修正します。

rollup.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が生成されます。以下のような感じになります。

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()プラグインに以下のような記述をして回避して下さい。

rollup.config.js
  plugins: [
    commonjs({
      namedExports: {
        'node_modules/react/index.js': [
          'createFactory',
          'Component',
          'createElement',
        ],
      },
    }),
  ]

その他エラー時

調子こいてステートレス関数なんか書いていくとコンパイルエラーになります。そういうときはエラーメッセージをよく読むと対応方法が書いてありますので確認してみて下さい。
自分の場合は @babel/plugin-proposal-class-propertiesを追加しました。

rollup.config.js
 /*...*/
    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 「その他」セクションを追加
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3