Chrome拡張の開発でwebpackを使わずにES6のimportを有効にしたい
追記 2018/10/29
chrome
モジュールが使えなくなる、という指摘は半分正しくて半分間違ってる(いくらでもやりようがある)のでもうちょっとちゃんとした記事を書きました。
以下原文ママ。
背景
- JSのプロジェクトで、特に僕はChrome拡張を作ることが多いんですが、ES6 syntaxを使いたい
- だいたいのES6 syntaxは、Chrome(現在 65.0.x)で使える
- ただし、問題は
import
です
Background Script でimportを使う
つまりHTML5準拠のブラウザでは<script type="module" src="..."></script>
とすれば、これをエントリポイントとして以下import
は解決されるんだけど、ということは逆にmanifest.json
のbackground.scripts
でBackgroundスクリプトを指定するとtype="module"
属性を与えられないので、わざわざbackground.page
を使ってそこから<script>
しましょうね、という話。
manifest.json
{ "background": { "page": "src/html/background.html" } }
src/html/background.html
<script type="module" src="src/js/background.js"></script>
Use ES6 import in Background Script · otiai10/chrome-extension-es6-import@ecf1267 · GitHub
Content Script でも、importを使いたい、のだが
同様の理由で、manifest.json
のcontent_scripts[i].js
でいきなりimport
を使っても
Uncaught SyntaxError: Unexpected identifier
となる。 Uncaught SyntaxError: Unexpected identifier · otiai10/chrome-extension-es6-import@154b321 · GitHub
どうにかして、HTMLを起因としたjsのロードをしたい。
scriptタグのインジェクション
manifest.json
の表現力では、どうにもcontent_script
のjsをtype="module"
でロードさせることができないので、<script>
タグそのものをページのHTMLに挿入すればよかろう、という発想。
まず、manifest.json
ではinject.js
を読ませる
manifest.json
"content_scripts": [ { "matches": ["<all_urls>"], - "js": ["src/js/content.js"] + "js": ["src/js/inject.js"] } ], "permissions": [
inject.js
では、<script>
タグの動的挿入を行う。
src/js/inject.js
(() => { const src = chrome.extension.getURL('src/js/content.js'); console.log(src); const script = document.createElement('script'); script.setAttribute('src', src); script.setAttribute('type', 'module'); document.body.appendChild(script); })();
いい感じに動きそうだが、これでも以下のエラーが出る。
GET chrome-extension://invalid/ net::ERR_FAILED
どうやらネットワークっぽいエラーで、jsのpathが正しく指定されていないか、あるいはもっと別の原因が考えられる。なお、inject.js
にconsole.log
させたsrc
のURLをクリックすれば正しくcontent.js
の内容が見えるので、pathが正しく指定されていない、ということはなさそう。
web_accessible_resources を指定すればよい
manifest.json
のweb_accessible_resources
というフィールドでは、ウェブからのリダイレクトなどの参照を許すChrome拡張内のリソースのパスを指定することができる。まさに今回、Chrome拡張側から見れば第三者の立場であるHTMLから、Chrome拡張内のリソースを<script src="...">
でロードさせようとしているので、これに該当する。
このとき、content.js
だけではなく、content.js
を起因とするすべてのimport
で参照されるリソースをweb_accessible_resources
に指定する必要があるので、ワイルドカードを使った。
], "permissions": [ "<all_urls>" + ], + "web_accessible_resources": [ + "src/js/*" ] }
いい感じに動いた。
ソースコードまとめ
懸念
node_modules
以下にあるパッケージをどうやってimpotするか- full pathを書けばimportできるだろうけれど、Chrome拡張としてリリースビルドにどう含めるか
- そもそもリリースビルドにnode_modules以下のすべてを含めるわけにはいかない
リリースするときminify・uglifyしたいという需要を考えたら、結局webpackなりのbundler使うのがよい、という結論なんだよな... くやしいけど。
— エロリツイート先生 (@otiai10) 2018年3月27日
結論
webpack使お...
DRY
初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発
- 作者: Ethan Brown,武舎広幸,武舎るみ
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/01/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質
- 作者: Cody Lindley,和田祐一郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/06/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
速習ECMAScript6: 次世代の標準JavaScriptを今すぐマスター! 速習シリーズ
- 作者: 山田祥寛
- 出版社/メーカー: WINGSプロジェクト
- 発売日: 2015/08/28
- メディア: Kindle版
- この商品を含むブログを見る