最初に結論から
現時点で僕が考えるベストプラクティスはこの組み合わせ。
- CDNのURLはwebpackからうまく指定できないので、HTML側の
<script>
タグ内に書く -
webpack.config.js
でexternals
を使ってHTML側のモジュールを利用 - アプリ側のJSコードで
import
する -
eslint-import-resolver-webpack
を使ってESLintにwebpackの設定を認識させる
具体例(コード抜粋)
Google API Client Library for JavaScriptをCDNで使う場合の例です。
eslint-plugin-importを使っていない場合
これがwebpackのオーソドックスな方法
externals
で外部にgapi
が存在することを教えてあげると、
アプリ側のJSコードでimport
することができます。
https://webpack.js.org/configuration/externals/
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
const webpack = require('webpack');
module.exports = {
// 中略
externals: {
gapi: 'gapi',
},
};
import gapi from 'gapi'
gapi.auth.authorize(
// 後略
eslint-plugin-importを使っている場合
上記のやり方でimport
すると、ESLintのimport/no-unresolved
に叱られます。
https://github.com/benmosher/eslint-plugin-import/blob/HEAD/docs/rules/no-unresolved.md
これはESLintがexternals
(というかwebpackの設定全体)を読み込めていないのが理由で、
eslint-import-resolver-webpack
を使ってwebpackの設定を読めるようにしてあげればOK。
https://www.npmjs.com/package/eslint-import-resolver-webpack
これが冒頭に箇条書きした「ベストプラクティス」です。
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
const webpack = require('webpack');
module.exports = {
// 中略
externals: {
gapi: 'gapi',
},
};
import gapi from 'gapi' // ここでエラーが出る
// エラーを気にしなければwebpackのビルド自体は通る
gapi.auth.authorize(
// 後略
# 前略
extends:
- standard
- plugin:import/errors
# ここまでが既に設定されていると仮定
# eslint-import-resolver-webpackパッケージをインストールして、
# 以下の2行を足してあげる
settings:
import/resolver: webpack
eslint-config-airbnbを使っている場合
記事公開時、最初に書いていた方法です。
この記事を公開した時点では、ESLintのプリセットとして
standard
ではなくairbnb-base
を使ってました。
https://www.npmjs.com/package/eslint-config-airbnb-base
これ厳しすぎて逆に開発効率落ちるので使うのやめたんですが、
import
に関するエラーも独特の厳しさがあり、
2番目に書いた方法ではエラーが取れなかったので、こんな風にしてたのでした。
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
const webpack = require('webpack');
module.exports = {
// 中略
externals: {
gapi: 'gapi',
},
plugins: [
new webpack.ProvidePlugin({ gapi: 'gapi' }),
],
};
// importはしない
gapi.auth.authorize(
// 後略
# 前略
globals:
gapi: true
no-extraneous-dependenciesとかextensionsあたりが面倒臭いんですよねー。
真っ当な解決方法があるのかもしれませんが、そこまで付き合ってられないので、
そもそもimport
するの自体を諦めて、こんなアプローチでやってます。
-
webpack.config.js
でexternals
を使ってHTML側のモジュールを利用 -
webpack.config.js
でwebpack.ProvidePlugin
を使ってグローバルっぽく使えるように設定 -
.eslintrc
のglobals
に該当モジュール名を記載してエラーが出ないように
しかしねぇ、気づいたんですよ。
「import
せずglobals
に追加」なんていう禁じ手を犯すんなら、
最初っからwebpackの仕組みは無視して、↓で十分なのですわ。。
【シンプル版】eslint-config-airbnbを使っている場合
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
// importはしない
gapi.auth.authorize(
// 後略
# 前略
globals:
gapi: true
webpack.config.js
自体は存在するけど、その中でgapi
については一切触れなくてもOK。
import
しないのでビルドもしれっと通ります。
webpackでGoogle APIを使う方法について
GitHubにこんなIssueが立ってて、
https://github.com/google/google-api-javascript-client/issues/319
こんな非公式ライブラリも紹介されてるんですが、
https://github.com/ryanjohnston/Load-Google-API
何となく将来性が疑問なので、webpackの標準方法でやってみました。
てゆーかwebpackからはNode.jsライブラリ使えるんだから、
公式のNode版を使えば良さそうにも思いますけどね。。これはまだ未検証。
https://github.com/google/google-api-nodejs-client
追記:リポジトリのIssueで、Googleの中の人が「サーバー専用だから無理」って回答してますね。
強引に使うハックもあるんでしょうが、そこまでがんばる必要ないと思うので、試すのはやめておきまーす。
@jmdobry commented on 9 May
It's not meant to be, as it's meant to be used on the server only. It doesn't need to be passed through any Webpack build.