SunriseDigital / ReactTest

0 stars 0 forks source link

WebPackについて #5

Open gomo opened 8 years ago

gomo commented 8 years ago

reactのような外部ライブラリを、importしても、外読みにしても使えるようにしたい。

browserifyを使って下記のようにしてとりあえず実現できた。

var browserify = require('browserify');
var source = require('vinyl-source-stream');

gulp.task('build-example', function() {
  browserify('example/todo/src/app.jsx', {
      debug: false,
      extensions: ['.jsx', '.es6']
    })
    .exclude('react', 'react-dom')
    .transform("browserify-replace", {replace: [
      {from: "import React from 'react';", to: ""},
      {from: "import ReactDOM from 'react-dom';", to: ""}
    ]})
    .transform("babelify", {presets: ["es2015", "react"]})
    .bundle()
    .on("error", function (err) {
      console.log('');
      console.log(err.message);
      console.log('' + err.codeFrame)
    })
    .pipe(source('todo.js'))
    .pipe(gulp.dest('example/todo/public'));
});

しかし、読み込んだライブラリがさらにrequireしていると読み込んでしまうようで、うまくいかなかった。

外部ライブラリのソースコードを読んでいたら、みんなWebPackというのを使っていて、もしかしたらそっちを使えばできるかもしれないのでやってみる。

https://webpack.github.io/

gomo commented 8 years ago

https://webpack.github.io/

関係ないけど、この公式のロゴのアニメーション、HTMLとCSSだけで実現してるっぽい。

gomo commented 8 years ago

http://liginc.co.jp/web/js/other-js/148813

割とわかりやすい日本語解説。

gomo commented 8 years ago

reactのような外部ライブラリを、importしても、外読みにしても使えるようにしたい。

いけそうな感じです。

externalsで代入してくれる。

module.exports = {
  entry: {
    List: './src/List.jsx'
  },
  output: {
      path: __dirname + '/web',
      filename: '[name].js'
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      loader: 'babel',
      query:
      {
          presets:['es2015', 'react']
      }
    }]
  }
}
gomo commented 8 years ago

どうやら、browserifyでもできていたようだ。うまくいかないと思っていたのは、試したプロジェクトでCssアニメーション用のReactTransitionGroupを使っていて、そいつの中身は下記のような実装になっていました。

module.exports = require('react/lib/ReactCSSTransitionGroup');

つまり、本体がreactの中にあって、react本体をrequireするのに、そのファイルの中で

var React = require('./React');

と、相対パスでrequireしていたので、externalの条件にマッチせずreactが全て取り込まれていたのが原因でした。

module.exports = {
  entry: __dirname + '/app.jsx',
  output: {
      path: 'path/to/build.js',
      filename: 'booking.js'
  },
  resolve: {
    extensions: ['', ".js", ".jsx", ".es6"]
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
    'react-addons-css-transition-group': 'React.addons.CSSTransitionGroup'
  },
  module: {
    loaders: [{
      test: /(\.jsx?$|\.es6?$)/,
      loader: 'babel',
      query:
      {
          presets:['es2015', 'react']
      },
      exclude: /node_modules/
    }]
  }
}

react-addons-css-transition-group自体もプロジェクトから除けば除外できます。

  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-with-addons.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.min.js"></script>

で、ページ読み込むのをreact-with-addons.min.jsにすればOKです。

まだ試してないですが、おそらくbrowserifyのexcludeを使っても同じことができるでしょう。

gomo commented 8 years ago

コンパイルのスピードについて

これも、もしかしたらwebpackに限った話ではなく、browserifyも同じかもしれないけど、gulpのwatchを使わずに、webpackのwatchオプションを使ったほうが断然コンパイルが早いです。

最初のコンパイルは同じですが、2度目から早いです。おそらくキャッシュが効いていて、変更された部分のみ挿入するとかですかね?

module.exports = {
  entry: __dirname + '/app.jsx',
  output: {
      path: 'path/to/build.js',
      filename: 'booking.js'
  },
  resolve: {
    extensions: ['', ".js", ".jsx", ".es6"]
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
    'react-addons-css-transition-group': 'React.addons.CSSTransitionGroup'
  },
  watch: true,
  module: {
    loaders: [{
      test: /(\.jsx?$|\.es6?$)/,
      loader: 'babel',
      query:
      {
          presets:['es2015', 'react']
      },
      exclude: /node_modules/
    }]
  }
}

んでもって、webpack --config path/to/webpack.config.jsで起動するか、gulpを使いたい場合は

gulp.task('build', function() {
  webpack(require('path/to/webpack.config.js'), function(err, stats) {
    if(err) throw new gutil.PluginError("webpack", err);
    gutil.log("[webpack]", stats.toString({
        // output options
    }));
  });
});

のような感じ。

webpack --config path/to/webpack.config.jsで起動すると、ファイルを変更せずただ保存した時タスクが走らないけど、gulpバージョンは走ります。大した差じゃないのでどちらでもいいかも。

ちなみに、試したプロジェクトでは、gulp-watchのとき、変更するたびに約2秒かかりますが、webpackのwatchだと50ミリ秒から200ミリ秒くらいです。断然こちらでやりましょう。