webpackと組み合わせて、簡単なJavaScriptでのテンプレートエンジンを使いたいと思いまして。
で、ちょっと事情からjQueryが視野に入らざるをえない感じなんですけど、jQueryでテンプレートといえばjQuery Templates plugin…
だと思っていたのですが、今は名を変えてJsRender/JsViews/JsObservableとなっているようです。
JsRender: best-of-breed templating
このあたりの事情、ホントに知らないなぁ…。
で、これとwebpackを合わせて使うことを考えまして、以下のような感じでやってみようかなと。
- 依存関係はBowerで解決(npmはちょっとムリでした)
- HTMLテンプレートは、webpackのhtml-loaderを使ってrequireするようにする
- webpack-dev-serverを利用して、コードに変更があったらオートリロード
ここまでの内容をやってみます。
追記)
Bowerなしで、チャレンジする方法も試してみました。
webpackとwebpack-dev-server、html-loaderと合わせて、JsRenderを試す(再) - CLOVER
準備
まずは、下準備から。以下のコマンドを実行します。
$ npm init $ npm install -g gulp webpack bower $ npm install --save-dev gulp gulp-util bower webpack webpack-dev-server html-loader $ bower init $ bower install --save jquery jsrender
html-loaderというのが、webpackのHTML Loaderです。
先ほどこういうエントリを書きまして
webpackを使ってJavaScriptのビルド/minify(+Bower) - CLOVER
ここでBower要らんのでは?というツッコミをいただいたのですが、JsRenderの場合「npm install」ではちょっと違う物が入ってしまうので、いろいろ試した挙句やめました。
GitHubのREADME.mdでは、以下のコマンドで良いことになっているのですが、
$ npm install jsrender --save
実際に実行すると、すでにメンテナンスが終了している以下のリポジトリのモジュールが引き込まれます。
https://github.com/shtylman/node-jsrender
関連っぽいもの…。
あまりハマり続けても仕方がないので、Bowerにしました。
コードの用意
動作確認用のコードはこちら。
まずは、HTML。
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>webpack/webpack-dev-server & JsRender example</title> </head> <body> <h1>webpack/webpack-dev-serverとJsRenderのサンプル</h1> <span>プログラミング言語</span> <span id="languages"></span> <script type="text/javascript" src="dist/scripts/app.js"></script> </body> </html>
エントリポイントとなるJavaScript。
src/scripts/main.js
var $ = require("jquery"); window.jQuery = $; var jsrender = require("jsrender"); //var template = require("html!../templates/list.html"); var template = require("html!html-templates/list.html"); var tmpl = $.templates(template); var scopes = { languages: ["Java", "JavaScript", "CoffeeScript"] }; $("span#languages").html(tmpl.render(scopes));
JsRenderのオブジェクトをそのまま使ってもよかったんですけど、jQueryと統合するには以下の1行を書くことに…。
window.jQuery = $;
これ、requireの追加引数とかにすればいいのかな?とも思いましたが、なんかダメっぽい。
言い換えれば、グローバルにjQueryがあれば、それに追加しにいくということですね…。
HTMLテンプレート。
src/templates/list.html
<ul> {{for languages}} <li>{{>}}</li> {{/for}} </ul>
JavaScriptは「src/scripts」、HTMLテンプレートは「src/templates」配下に置いています。
$ find index.html src -type f index.html src/templates/list.html src/scripts/main.js
gulpの設定
gulpfile.jsは、以下のようになりました。
gulpfile.js
var gulp = require("gulp"); var gutil = require("gulp-util"); var webpack = require("webpack"); var WebpackDevServer = require("webpack-dev-server"); var webpackConfig = require("./webpack.config.js"); gulp.task("default", ["webpack-dev-server"]); gulp.task("webpack", function(callback) { var config = Object.create(webpackConfig); webpack(config, function(err, stats) { if(err) throw new gutil.PluginError("webpack", err); gutil.log("[webpack]", stats.toString({ colors: true })); callback(); }); }); gulp.task("webpack-dev-server", function(callback) { var config = Object.create(webpackConfig); var compiler = webpack(config); new WebpackDevServer(compiler, { publicPath: "/" + config.output.publicPath, stats: { colors: true } }).listen(8080, "localhost", function(err) { if(err) throw new gutil.PluginError("webpack-dev-server", err); gutil.log("[webpack-dev-server]", "http://localhost:8080/webpack-dev-server/index.html"); // keep the server alive or continue? callback(); }); });
webpack-dev-serverのリッスンポートは、以下のサンプルに習って8080に。
このあたりを参考にしています。
http://webpack.github.io/docs/usage-with-gulp.html
https://github.com/webpack/webpack-with-common-libs/blob/master/gulpfile.js
webpackの設定
webpackの設定は、このように行いました。
webpack.config.js
var path = require("path"); var webpack = require("webpack"); var currentWorkingDirectory = process.cwd(); module.exports = { cache: true, entry: { app: "./src/scripts/main.js" }, output: { path: path.join(__dirname, "dist/scripts"), publicPath: "dist/scripts/", filename: "[name].js", chunkFilename: "[chunkhash].js", // sourceMapFilename: "[file].map" }, loaders: [ { test: "/\.html$/", loader: "html?minize" } ], resolve: { root: [path.join(__dirname, "bower_components")], alias: { "html-templates": currentWorkingDirectory + "/src/templates" } }, devtool: "#source-map", plugins: [ new webpack.ResolverPlugin( new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"]) ), new webpack.DefinePlugin({ "process.env": { // This has effect on the react lib size "NODE_ENV": JSON.stringify("production") } }), new webpack.optimize.DedupePlugin(), new webpack.optimize.UglifyJsPlugin() ] };
html-loaderに関しては、npmでインストールしたうえで、以下を追加。
loaders: [ { test: "/\.html$/", loader: "html?minize" } ],
これで、このような記述でテンプレートをロードすることが可能になります。
var template = require("html!../templates/list.html");
が、これだと現在のスクリプトからの相対パスになるので、なんか微妙だなぁと思ってこういう記述に変更。
var template = require("html!html-templates/list.html");
これを動作させるために、aliasを貼りました。
alias: { "html-templates": currentWorkingDirectory + "/src/templates" }
currentWorkingDirectoryというのは、以下の内容です。
var currentWorkingDirectory = process.cwd();
はい。
このあたりは、こちらを参考に。
https://github.com/webpack/webpack-with-common-libs/blob/master/webpack.config.js
http://webpack.github.io/docs/using-loaders.html
https://webpack.github.io/docs/list-of-loaders.html
確認
gulpでwebpack-dev-serverを起動するようにしているので、以下のコマンドを実行。
$ gulp
こんな内容が出力されまして…
[23:00:04] Using gulpfile ~/xxxxx/gulpfile.js [23:00:04] Starting 'webpack-dev-server'... [23:00:04] [webpack-dev-server] http://localhost:8080/webpack-dev-server/index.html [23:00:04] Finished 'webpack-dev-server' after 57 ms [23:00:04] Starting 'default'... [23:00:04] Finished 'default' after 6.16 μs Hash: a21d5a9e49bf19575d1b Version: webpack 1.12.2 Time: 4173ms Asset Size Chunks Chunk Names app.js 103 kB 0 [emitted] app app.js.map 894 kB 0 [emitted] app chunk {0} app.js, app.js.map (app) 318 kB [rendered] [0] ./src/scripts/main.js 354 bytes {0} [built] [1] ./bower_components/jquery/dist/jquery.js 248 kB {0} [built] [2] ./bower_components/jsrender/jsrender.js 69.9 kB {0} [built] [3] ./~/html-loader!./src/templates/list.html 68 bytes {0} [built] WARNING in app.js from UglifyJs Side effects in initialization of unused variable jsrender [./src/scripts/main.js:4,0] Condition always true [./bower_components/jquery/dist/jquery.js:9170,0] Condition always true [./bower_components/jsrender/jsrender.js:19,0] Dropping unreachable code [./bower_components/jsrender/jsrender.js:21,2] Side effects in initialization of unused variable $ [./bower_components/jsrender/jsrender.js:17,0] Dropping unused variable tag_ [./bower_components/jsrender/jsrender.js:450,0] webpack: bundle is now VALID.
URLがログにも出ていますが、以下にアクセスすると
http://localhost:8080/webpack-dev-server/index.html
なお、gulp起動中にファイルを修正すると、webpack-dev-serverが変更を反映してくれます。
以上!