LoginSignup
25
15

More than 5 years have passed since last update.

webpackでnpmでないCDNのライブラリを読み込んでESLint対応

Last updated at Posted at 2017-10-12

最初に結論から

現時点で僕が考えるベストプラクティスはこの組み合わせ。

  • CDNのURLはwebpackからうまく指定できないので、HTML側の<script>タグ内に書く
  • webpack.config.jsexternalsを使って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/

gapi.html
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
webpack.config.js
const webpack = require('webpack');

module.exports = {
  // 中略

  externals: {
    gapi: 'gapi',
  },
};
app.js
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

これが冒頭に箇条書きした「ベストプラクティス」です。

gapi.html
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
webpack.config.js
const webpack = require('webpack');

module.exports = {
  // 中略

  externals: {
    gapi: 'gapi',
  },
};
app.js
import gapi from 'gapi' // ここでエラーが出る

// エラーを気にしなければwebpackのビルド自体は通る
gapi.auth.authorize(
  // 後略
.eslintrc.yml
# 前略
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番目に書いた方法ではエラーが取れなかったので、こんな風にしてたのでした。

gapi.html
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
webpack.config.js
const webpack = require('webpack');

module.exports = {
  // 中略

  externals: {
    gapi: 'gapi',
  },

  plugins: [
    new webpack.ProvidePlugin({ gapi: 'gapi' }),
  ],
};
app.js
// importはしない
gapi.auth.authorize(
  // 後略
.eslintrc.yml
# 前略
globals:
  gapi: true

no-extraneous-dependenciesとかextensionsあたりが面倒臭いんですよねー。
真っ当な解決方法があるのかもしれませんが、そこまで付き合ってられないので、
そもそもimportするの自体を諦めて、こんなアプローチでやってます。

  • webpack.config.jsexternalsを使ってHTML側のモジュールを利用
  • webpack.config.jswebpack.ProvidePluginを使ってグローバルっぽく使えるように設定
  • .eslintrcglobalsに該当モジュール名を記載してエラーが出ないように

しかしねぇ、気づいたんですよ。
importせずglobalsに追加」なんていう禁じ手を犯すんなら、
最初っからwebpackの仕組みは無視して、↓で十分なのですわ。。

【シンプル版】eslint-config-airbnbを使っている場合

gapi.html
<!-- 前略 -->
<script src="https://apis.google.com/js/api.js"></script>
app.js
// importはしない
gapi.auth.authorize(
  // 後略
.eslintrc.yml
# 前略
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.

参考サイト

25
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
15