はじめに
この章では以下の内容について説明します。
- typscript実行環境の作り方
-
tsconfig.json
の記述方法
Cloud Run functionsでのTypeScript環境の作り方は人によってバラバラで「コレ!」という方法が今のところ見つかっていない感じがあります。
しかし僕的には本記事(と次の記事)で紹介する方法が一番シンプルでスマートだと思います。
想定ディレクトリ
├── package.json
├── package-lock.json
└── src
└── index.ts
前回と異なる点は、ソースファイルを格納するsrc
ディレクトリを作成し、そこにソースコードをぶち込むようにしています。
TypeScript実行環境の構築
typescriptパッケージのインストール
npm install --save-dev typescript
これによってtsc
コマンドが使えるようになり、index.ts
→ index.js
にトランスパイル(簡単にいうと変換)できるようになります。
tsconfig.json
の作成
実は tsconfig.json
は別に作らなくてもtypescirpt使えます。がだと言って作らないでおくと色々面倒なので作っておきましょう。
tsc --init
で tsconfig.json
が作成されます。
...が、使いづらいので使いません。試しに実行してみましょう。
npx tsc --init
Created a new tsconfig.json with:
target: es2016
module: commonjs
strict: true
esModuleInterop: true
skipLibCheck: true
forceConsistentCasingInFileNames: true
You can learn more at https://aka.ms/tsconfig
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// ...
...ほとんどコメントアウト...😅
見にくいし、全くあんまり使えません。
2024年現在、Cloud Run functions用にスクラッチから作るなら以下のようになると思います。
{
"compilerOptions": {
"target": "es2022",
"module": "node16",
"moduleResolution": "node16",
"baseUrl": "./src",
"paths": {
"@/*": ["./*"]
},
"rootDirs": ["./src"],
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules"]
}
特に説明した方がよさそうな項目について説明していきます。
target
TS → JSへのトランスパイル時にどのバージョンのJavaScriptで出力するかを記載します。
es2023
以下に設定するのが適切そうですが、es2022
にしておきます。理由は後述します。
module
トランスパイスしたJSを動かす環境が期待しているモジュール形式です。
Node.jsの設定値で正しいのは node16
か nodenext
です。 commonjs
と esnext
を設定するのは誤りのようです。
Node.js’s rules for module format detection and interoperability make it incorrect to specify module as esnext or commonjs for projects that run in Node.js, even if all files emitted by tsc are ESM or CJS, respectively.
nodenext
ではバージョンが動的に変わってしまうため、node16
に設定します。
そして node16
に設定すると暗示的に target
は es2022
に、moduleResolution
は node16
に変わるみたいです。target
を es2023
にしなかったのはこの理由からです。
設定する意味ないぢゃん!
Moduleの話は公式リファレンスでも詳しく説明されていますので、参考ください。
baseUrl
どこを起点にモジュール解決するかの設定。
例えば、以下のようなディレクトリ構成でbaseUrl
を./src
とした場合、
project_root
└─ src
├── services
│ ├── product.ts
│ └── order.ts
├── lib
│ └── time.ts
└── index.ts
src/service/product.ts
から src/lib/time.ts
を相対パスを使わないで参照する場合、以下の記述でファイル参照ができます。
import time from 'lib/time';
もちろん、相対パスは通常通り使えます。
import time from '../lib/time';
ただ、以下はNGです。
import time from 'order'; // ./src/order.ts が参照される
rootDirs
どのディレクトリ階層以降をコンパイル対象にするかの設定。
./src
より前のディレクトリ階層を指定しようとするとエラーになる。
project_root
├── src
│ ├── services
│ │ ├── product.ts
│ │ └── order.ts
│ ├── lib
│ │ └── time.ts
│ └── index.ts
└── sample.ts
以下の呼び出しはNGになります。
import sample from '../../sample'; // NG
paths
モジュール解決の際にエイリアスを設定できるオプション。
baseUrl
を指定するとその位置を基準にとしてエイリアスが設定される。
// ...
"paths": {
"@/*": ["./*"] // @/xxx で src/xxx を指定したのと同じ
},
例えば以下のようにできる。
// import time from '../lib/time' がスッキリする
import time from '@/lib/time';
ただし注意ですが、tscによるトランスパイル後のJSファイルを実行しようとするとエラーになります。
src/index.ts:2:24 - error TS2307: Cannot find module '@/xxx' or its corresponding type declarations.
トランスパイル後のJSファイルを見てみるとわかるのですが、エイリアスがそのまま出力されており、パス解決ができない状態になっています。
var sample_1 = require("@/test/sample"); // エイリアスがそのまま出力されてしまっている
大事なことなのですが、トランスパイルしただけではimportのパス解決はできません。 別途ビルドツールを使ってモジュール解決できるよう変換する必要があります(違っていたら教えてください)。
次章以降でこの解決方法を紹介していきます。
おわりに
こうして構築した環境を利用して、次の記事ではTypeScript上でCloud Run functions関数を実行する方法を紹介していきます。
参考文献