benvを使ってangular.jsのコードをnode上で動作させる
はじめに
テストなどを書きたい時にブラウザを立ち上げずに動作チェックなどをしたいことがある。 しかしangular.jsを直接nodeからrequireすると怒られる
$ npm install --save angular $ node -p 'require("angular")' ReferenceError: window is not defined at Object.<anonymous> (/home/podhmo/tmp/angular-api-test/node_modules/angular/angular.js:29016:4) at Module._compile (module.js:435:26) at Object.Module._extensions..js (module.js:442:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:311:12) at Module.require (module.js:366:17) at require (module.js:385:17) at Object.<anonymous> (/home/podhmo/tmp/angular-api-test/node_modules/angular/index.js:1:63) at Module._compile (module.js:435:26) at Object.Module._extensions..js (module.js:442:10)
benvを使う
artsy/benv を使うとjsdomでwrapした環境が手に入るらしい。 以下の記事を参考にした。
about benv
artsy/benv はjsdomのwrapperの模様。
Stub a browser environment and test your client-side code in node.js.
以下の様なコードを書く
// loadSample.js 'use strict'; var benv = require('benv'); function setup(cb){ benv.setup(function(){ global.Node = window.Node; benv.expose({ angular: benv.require('./node_modules/angular/angular.js', 'angular') }); cb(); }); } setup(function(){ console.log('window is', typeof window); console.log('document is', typeof document); console.log('angular is', typeof angular); console.log('window.angular === angular', window.angular === angular); });
以下の様に実行できる。
$ node loadSample.js window is object document is object angular is object window.angular === angular true
global.Node = window.Node
について
参考にした記事に従ってコードを書いた時以下の様なエラーが発生した。これを防ぐために追加している。
ReferenceError: Node is not defined at /home/podhmo/tmp/angular-api-test/node_modules/angular/angular.js:2789:22 at /home/podhmo/tmp/angular-api-test/node_modules/angular/angular.js:29016:3 at Object.<anonymous> (/home/podhmo/tmp/angular-api-test/node_modules/angular/angular.js:29116:4) at Module._compile (module.js:435:26) at Object.Module._extensions..js (module.js:442:10) at Module.load (module.js:356:32) at Object.load (/home/podhmo/tmp/angular-api-test/node_modules/rewire/lib/moduleEnv.js:20:18) at internalRewire (/home/podhmo/tmp/angular-api-test/node_modules/rewire/lib/rewire.js:57:15) at rewire (/home/podhmo/tmp/angular-api-test/node_modules/rewire/lib/index.js:11:12) at Object.module.exports.require (/home/podhmo/tmp/angular-api-test/node_modules/benv/index.js:69:13)
gist
gistにしてみた。
https://gist.github.com/podhmo/c17f6e7b720019787729
追記
このままだとangularをどうやって使うかはわからないのでsampleも書いてみた。
// appSample.js 'use strict'; var benv = require('benv'); function setup(cb){ benv.setup(function(){ global.Node = window.Node; benv.expose({ angular: benv.require('./node_modules/angular/angular.js', 'angular') }); cb(); }); } setup(function(){ angular.module('myApp', []) .controller('helloController', ['$scope', function ($scope) { $scope.title = 'Node!'; }]); document.body.innerHTML = '<div ng-controller="helloController">{{ title }}</div>'; angular.bootstrap(document, ['myApp']); console.log(angular.element(document.body).html()); });
以下の様な出力になる
$ node appSample.js <div ng-controller="helloController" class="ng-scope ng-binding">Node!</div>