ぎゃーてー

システム開発のメモ

webpack時に許されない dynamic import (require) の書き方

概要

次のように、動的インポートを含むコードをWebpackでコンパイルしようとすると、エラーが発生します。

const _ = require(`@/${variable}`)

具体的なエラー全文は長くなるので末尾に記載しますが、だいたいこんな感じの出力になります。

パースしてはだめなものまでパースしようとして失敗しているような表記なので紛らわしいですね。

ERROR in ./Dockerfile 1:5
Module parse failed: Unexpected token (1:5)

ERROR in ./tsconfig.json
Module parse failed: Unexpected token / in JSON at position 110 while parsing near '...le": "esnext",

ERROR in ./yarn.lock 1:1
Module parse failed: Unexpected character ' ' (1:1)

解決

Webpackで静的にコンパイルする時点で対象ファイルのパスが分からなくなっているようです。 次のようにすれば解消されます。

const _ = require(`@/path/${variable}`)

ref

github.com

ちなみにこのリンクを見るとエイリアス @ を使用しない場合も症状が発生するようですが、 再現しませんでした。

エラー全文(一部)

asset server.js 320 KiB [emitted] (name: main)
runtime modules 937 bytes 4 modules
modules by path ./ 700 KiB
  modules by path ./src/ 187 KiB 61 modules
  modules by path ./config/ 8.98 KiB 9 modules
  modules by path ./__tests__/ 7.98 KiB 7 modules
  modules with errors 477 KiB [errors] 6 modules
  modules by path ./data/abis/*.js 7.7 KiB 3 modules
  ./app.ts 1.7 KiB [built] [code generated]
  .// sync ^\.\/.*$ 6.06 KiB [built] [code generated]
  ./package.json 3.17 KiB [optional] [built] [code generated]
modules by path external "@google-cloud/ 84 bytes
  external "@google-cloud/firestore" 42 bytes [built] [code generated]
  external "@google-cloud/storage" 42 bytes [built] [code generated]
28 modules

ERROR in ./Dockerfile 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> FROM node:14-alpine
| WORKDIR /usr/src/app
| # ENV DOCKERIZE_VERSION v0.6.1
 @ .// sync ^\.\/.*$ ./Dockerfile
 @ ./src/v1/helpers/session.ts 36:27-72
 @ ./src/v1/helpers/index.ts 5:0-32 22:18-25
 @ ./src/v1/index.ts 22:0-32 61:40-47 69:96-103
 @ ./src/index.ts 2:0-22 5:17-19
 @ ./app.ts 9:0-24 18:16-19

ERROR in ./tsconfig.json
Module parse failed: Unexpected token / in JSON at position 110 while parsing near '...le": "esnext",

You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
SyntaxError: Unexpected token / in JSON at position 110 while parsing near '...le": "esnext",

 @ .// sync ^\.\/.*$ ./tsconfig.json ./tsconfig
 @ ./src/v1/helpers/session.ts 36:27-72
 @ ./src/v1/helpers/index.ts 5:0-32 22:18-25 @ ./src/v1/index.ts 22:0-32 61:40-47 69:96-103 @ ./src/index.ts 2:0-22 5:17-19
 @ ./app.ts 9:0-24 18:16-19

ERROR in ./yarn.lock 1:1
Module parse failed: Unexpected character ' ' (1:1)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
| # yarn lockfile v1
|
 @ .// sync ^\.\/.*$ ./yarn.lock
 @ ./src/v1/helpers/session.ts 36:27-72
 @ ./src/v1/helpers/index.ts 5:0-32 22:18-25
 @ ./src/v1/index.ts 22:0-32 61:40-47 69:96-103
 @ ./src/index.ts 2:0-22 5:17-19
 @ ./app.ts 9:0-24 18:16-19

gcloud系インスタンスをkeyFilenameを使わないで初期化する

前提

GCP のプロジェクト(cloud storage や firestore, firebase)を初期化するときに、大抵は次のようにファイルパスを指定するようになっています。

const Firestore = require('@google-cloud/firestore')

const firebaseConfig = {
  projectId: 'YOUR_PROJECT_ID',
  keyFilename: '/path/to/keyfile.json',
}
const db = new Firestore(firebaseConfig)

ファイルの取り回しは面倒です。

  • クラウドやdockerなど実行環境でパスが変わる
  • webpackでパスが変わる
  • require(`@/config/keyfile.json`) みたいにテンプレートリテラルが使いたい
  • 意図的に非同期処理しないといけない

解決

以下のように credentials: {private_key, client_email} が指定できます。

const serviceAccount = require(`@/keyfile.json`)

const firebaseConfig = {
  credentials: {
    private_key: serviceAccount.private_key,
    client_email: serviceAccount.client_email,
  },
  projectId: serviceAccount.project_id
}

const db = new Firestore(firebaseConfig)

ソース

ここで議論されていました。 github.com

また、このソースはここです。

github.com