仕事の中でjsの開発環境を構築する機会があったので、自前でes6をコンパイルする環境をととえてみた備忘録。
jsは動きが早くて色んなツールが出て来るなか、一定出尽くして落ち着いてきそうな感じをここ最近感じていたので、ようやく少しずつキャッチアップしていこうと思いました。
サマリ
- yarn + webpack導入
- es6を動かす
- es6で書いたコードを動かす
どうしてyarnにしてのか
yarnとは?
facebookが開発したnext npm的なポジションのpackageマネージャー
去年10月にローンチして、徐々に使用事例が多くなってきたので自前でjsのモダンな開発環境を作るにあたって採用してみようと思ったから。
yarnのいいところ
https://qiita.com/0829/items/ec5271c06f8ff0633dd3 あたりを参考にした。
npmが生成した package.json
を読み込める用に作られているので、npmとの互換性が保たれているので、正直どちらを使ってもいいと思われるが、npmより高速に動作し、依存関係やバージョン等も厳格に管理することができるため、npmでもできるが、yarnを積極的に使わない理由も弱い。
といった感想を持っている。
導入手順
yarn init
$ mkdir MyProject $ cd MyProject $ yarn init yarn init yarn init v1.1.0 ... success Saved package.json
対話式でプロジェクトの概要をセットアップしていく。
完了したらpackage.jsonができる
babelの設定
babelを使う場合は、 .babelrc
が必要なものかと思ってましたが、webpackの場合は webpack.config.js
にコンパイルの定義を書けます。
babelと一緒にes2015(es6)の構文対応できるように、 babel-preset-env
をインストールします。
$ yarn add -D babel-loader babel-core babel-preset-env
当初 babel-preset-es2015
を入れてましたが、yarn add している最中に warning babel-preset-es2015@6.24.1: 🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
というwarnを受けたので、 babel-preset-env
を入れました。
refs: https://babeljs.io/env/
github: https://github.com/babel/babel-preset-env
webpack.config.jsの設定
- entryとoutputについて
http://dackdive.hateblo.jp/entry/2016/04/13/123000 を参考にしました。
コンパイル元のファイルはentryに書いて、1つに固めたファイルの出力先がoutput。
というわけで出来上がった webpack.config.js
はこちら
const src = __dirname + "/src"; const dist = __dirname + "/dist" var webpack = require('webpack'); module.exports = { context: src, entry: "./index.js", output: { path: dist, filename: "index.min.js" }, module: { loaders: [ { test: /\.js$/, exclude:/node_modules/, loader: "babel-loader", query: { presets:[ ["env"] ] } } ] } };
es6の導入
ディレクトリ構成は以下
MyProject src index.js dist index.min.js
このindex.jsにes6の構文で書いて、コンパイル後index.min.jsがちゃんと読み込まれるかを確認する
おまけ
難読化(UglifyJS)
コンパイルしたファイルを難読化する。
webpackには標準でUglifyJSがあるので、これを plugins
に追加したが、defaultの難読化プラグインはコンパイル時にエラーが発生した
$ yarn run build yarn run v1.1.0 $ yarn run --config webpack Hash: 2689b764da6353bc4101 Version: webpack 3.6.0 Time: 341ms Asset Size Chunks Chunk Names index.min.js 3.11 kB 0 [emitted] main [0] ./index.js 371 bytes {0} [built] [1] ./person.js 162 bytes {0} [built] ERROR in index.min.js from UglifyJs Unexpected token: name (Friend) [index.min.js:79,6] error Command failed with exit code 2. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
標準のuglify-jsが動かなかったので、uglifyjs-webpack-pluginを使う
refs: https://www.npmjs.com/package/uglifyjs-webpack-plugin
$ yarn add -D uglifyjs-webpack-plugin
const src = __dirname + "/src"; const dist = __dirname + "/dist" var webpack = require('webpack'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin') //追加 module.exports = { context: src, entry: "./index.js", output: { path: dist, filename: "index.min.js" }, module: { loaders: [ { test: /\.js$/, exclude:/node_modules/, loader: "babel-loader", query: { presets:[ ["env", { "targets": { "node": "current" } }] ] } } ] }, plugins: [ new UglifyJSPlugin() //追加 ] };
webpackを動かす
yarn run build yarn run v1.1.0 $ yarn run --config webpack Hash: 2689b764da6353bc4101 Version: webpack 3.6.0 Time: 381ms Asset Size Chunks Chunk Names index.min.js 786 bytes 0 [emitted] main [0] ./index.js 371 bytes {0} [built] [1] ./person.js 162 bytes {0} [built] ✨ Done in 1.37s. $ cat dist/index.min.js !function(e){function t(n){if(r[n])return r[n].exports;var u=r[n]={i:n,l:!1,exports:{}};return e[n].call(u.exports,u,u.exports,t),u.l=!0,u.exports}var r={};t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,r){"use strict";var n=function(e){return e&&e.__esModule?e:{default:e}}(r(1));class u extends n.default{constructor(e){super(name)}callName(){alert(this.name)}}new u("Taro").callName()},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});class n{constructor(e){this.n=e}}t.default=n}]);⏎
ちゃんと難読化されている。
動かしてみる
webpackにはlocalにサーバーを立てるライブラリ webpack-dev-server
があるのでこちらを使う
$ yarn add -D webpack-dev-server $ yarn run webpack-dev-server //これで動作させることができる。
上記でも問題ないがscriptを作成した
"scritps": { "start": "yarn run webpack-dev-server" "build":... }
devserverはデフォルトは8080ポートで動作するが、手元のgoとパッティングするので3000番portに変更。
以下を webpack.config.json
に追加する
const src = __dirname + "/src"; const dist = __dirname + "/dist" var webpack = require('webpack'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin') module.exports = { context: src, entry: "./index.js", output: { path: dist, filename: "index.min.js" }, devServer: { contentBase: dist, port: 3000 }, module: { loaders: [ { test: /\.js$/, exclude:/node_modules/, loader: "babel-loader", query: { presets:[ ["env", { "targets": { "node": "current" } }] ] } }, // 以下でhtmlの読み込みも追加する { test: /\.html$/, loader: "file?name=[path][name].[ext]" } ] }, plugins: [ new UglifyJSPlugin() ] };
サーバーを起動させる
yarn run start yarn run v1.1.0 $ yarn run webpack-dev-server Project is running at http://localhost:3000/ webpack output is served from / Content not from webpack is served from ~/emahiro/es6_sample/dist Hash: 093cadee3f8742a9e298 Version: webpack 3.6.0 Time: 2247ms Asset Size Chunks Chunk Names ... webpack: Compiled successfully.
注目すべきは以下
webpack output is served from / Content not from webpack is served from ~/emahiro/es6_sample/dist
サーブされているのは /
だけど、実際にはdistがwebから見たときのcontentのrootになる
dist index.min.js
というディレクトリ構造をしている場合、htmlからjsを呼び出すときは ./index.min.js
と直書きする。
サーバーが起動した状態で localhost:3000
にアクセスしたら alert
が発火するはず。
発火したら正常にes6がコンパイルされて動作していることになる。
所感
今までjsの潮流が早すぎて、正直足突っ込んだら抜けられなくなりそうだったので、避けてきた分野でしたが、webpackを使うことでjsド素人でも簡単にes6をプロジェクトに取り入れることが出来ました。
色々試せそうですが、次はtypescript入れてコンパイルしてみようと思います。