まずnew Worker(“./my/worker”) というやつ
Workerのコンストラクタにファイルパスを渡すやつからしてwebpackだとどう解決されるのか問題。
以上を参考にして、まず
npm install --save-dev worker-loader
つぎに、webpack.config.jsで
var plugins = [ new webpack.LoaderOptionsPlugin({ options: { worker: { output: { filename: "dest/js/worker.[id].js", } } } }) ];
として、自作のWorkerを使いたいほうは、
var Worker = require("worker-loader?inline!../../../Workers/my/worker");
とかしとくと
webpack 2.2の標準出力では
Child worker: Asset Size Chunks Chunk Names dest/js/worker.0.js 4.59 kB 0 [emitted] main [1] ./~/babel-loader/lib!./src/js/Components/Workers/my/worker.js 1.24 kB {0} [built] + 1 hidden modules
となって、生成物としては、以下の648がWorkerを引っ張る共通処理、649が、648を使って自作のWorkerを提供する処理になっているので、
/***/ 648: /***/ (function(module, exports) { // http://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string var URL = window.URL || window.webkitURL; module.exports = function(content, url) { try { try { var blob; try { // BlobBuilder = Deprecated, but widely implemented var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; blob = new BlobBuilder(); blob.append(content); blob = blob.getBlob(); } catch(e) { // The proposed API blob = new Blob([content]); } return new Worker(URL.createObjectURL(blob)); } catch(e) { return new Worker('data:application/javascript,' + encodeURIComponent(content)); } } catch(e) { return new Worker(url); } } /***/ }), /***/ 649: /***/ (function(module, exports, __webpack_require__) { module.exports = function() { return __webpack_require__(648)("/** 略 **/", __webpack_require__.p + "dest/js/worker.0.js"); };
このWorkerを使いたいほうでは、649を使ってWorkerインスタンスを作っていることが予想される。以下の通り。
var Worker = __webpack_require__(649); const worker = new Worker();
となって、うまいことWorkerをwebpackでロードできている感じになった。
importScriptsがどこなの問題
このエントリ書いてるのが2017/02/19 (CET) で、このissueが立ったのが02/08、コントリビュータがbug
のlabelをつけたのが02/17なので、なかなかホット。実際、webpackの成果物で、importScripts
をしている部分を見ると、
前
importScripts("../foo.js", "../bar.js");
後
importScripts("../foo.js", "../bar.js");
となっており、webpack@2.2.1の時点でimportScripts
内のコンテキストは解決されず、生成されたworkerなjsファイル(今回のケースでいうとdest/js/worker.0.js
)に対する相対pathを書く必要がある。
TODO: このissueに動きがあったらここに追記する
番外: Chrome拡張において
Chrome拡張においてうまいことdest/js/worker.0.js
というworkerから相対pathでimportScriptsしてくれなかったので、完全なURLを渡す必要があり、以下のようにした。
自作Worker
import imports from "../imports"; const _init = (data) => { imports(data.root)("dest/js/nice-lib-x.js", "dest/js/cool-lib-y.js"); }; onmessage = (ev) => { switch(ev.data.cmd) { case "init": return _init(ev.data); case "なんか他のこといろいろ": return _awesome_action(ev.data); default: return; }; };
自作べんりimports関数
/** * Workerのコンテキストではchromeは参照できないので、 * Chrome拡張自体の持つルートディレクトリのURLを * アプリケーション側からもらって、それをimportScriptsする必要があるよ。 */ export default function imports(root) { return function() { // ↑ // ここをアローで書くと、argumentsの参照がwebpackによって // カリー化関数自体のargumentsに固定されてしまうので // functionキーワードで書く必要がある if (!root) throw "importScriptsする場合は必ずrootを指定してください"; const _root = root.replace(/\/+$/, "/"); // ケツの/の重複をきれいにするだけ importScripts(...Array.prototype.map.call(arguments, path => _root + path)); }; }
自作Worker呼ぶ方
var Worker = require("worker-loader?inline!../../../Workers/my/worker"); const worker = new Worker(); worker.postMessage({ cmd: "init", root: chrome.extension.getURL("/") });
これでうまい感じに
chrome-extension://{extensionId}/dest/js/nice-lib-x.js
に定義した色々が自作Workerの中でアレできるようになった。
雑感
- webpackちょっとわかってきた
- さいきんReact/ReactNativeばっかり書いてて頭おかしくなりそう
- ベルリンのスタートアップはいろいろつらい。早く日本に帰りたい
- ベルリンは好きだ
- ビール安い
- ソーセージをはじめ、肉が安い
- 食材が安いので料理がたのしい
- SAOの劇場版、ドイツでやってるっぽい
DRYな備忘録として
初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発
- 作者: Ethan Brown,武舎広幸,武舎るみ
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/01/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
改訂新版JavaScript本格入門 ?モダンスタイルによる基礎から現場での応用まで
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2016/09/30
- メディア: Kindle版
- この商品を含むブログを見る