Open3

Fast API + TypeScript で開発する際に困ったこと

NoiNoi

概要

困ったことをメモ的に書いていきます。
他にも同じ状況でこんなこと困りましたとか、あれば自由にコメントOKです。

なぜFast APIか

筆者が今後機械学習や数値計算を使っていきたいと思っているため。

なぜDjangoじゃないのか

Fast APIの方が簡単に作れるから。

なぜTypeScriptか

WebGLを使って3D表現をしたいのでthree.jsをつかいたい。
そーなるとJavaScriptを書かなきゃいけないんだけれども、
動的型付け言語だと補完が効かなかったり、
ブラウザ上で実行するまでエラーが分からなかったりする。

よーするに、開発効率、保守性を上げたいから。

ファイル構成

app
  ├ node_module
  |   ├ @types
  |   |   └ three
  |   |      └ index.d.ts
  |   └ three.js-master
  ├ static
  |   ├ build
  |   ├ typescript
  |   └ three.js-master
  ├ templates
  ├ controllers.py
  ├ models.py
  ├ database.py
  └ run.py
NoiNoi

OSSのライブラリをimportしても補完が効かない!!

node.jsnpmで型を取得しなきゃいけない。

npm install @types/three

Moduleと型ファイルを同じ名前でimportできない。

【NG】myFirstProject.ts
import * as THREE from '../three.js-master/build/three.module.js';
import * as THREE from '../../node_module/@types/three/index';

非相対インポートをする。

【OK】myFirstProject.ts
import * as THREE from 'three';

JavaScriptにコンパイルすると、モジュールが読み込めない

コンパイル時に相対インポートに書き換える。
だが、この作業をコンパイル時に毎回やるのはめんどくさい。
何とかならんもんかと解決策を模索中。

Before
import * as THREE from 'three';
//import * as THREE from '../three.js-master/build/three.module.js';
After
//import * as THREE from 'three';
import * as THREE from '../three.js-master/build/three.module.js';

解決策

import文を変換するpythonスクリプトを作成する。

changeImport.py
file_lists = [
    "../build/myFirstProject.js", 
]

target_strs = [ 
    "import * as THREE from 'three';", 
    "import 'stats';", 
    "import * as dat from 'dat.gui';"
]

replaced_strs = [ 
    "import * as THREE from '../node_modules/three/build/three.module.js';\n" ,
    "import Stats from '../node_modules/three/examples/jsm/libs/stats.module.js';\n",
    "import * as dat from '../node_modules/dat.gui/build/dat.gui.module.js';\n",
]

print('File exchange start.')

for file_name in file_lists:
    with open(file_name, 'r') as f:
        lines = f.readlines()

    with open(file_name, 'w') as f:
        for line in lines:
            for i in range(len(target_strs)):
                if line.startswith(target_strs[i]):
                    line = replaced_strs[i]
                #line.replace(target_strs[i], replaced_strs[i])
            f.write(line)
        
print('File exchange completed.')

さらに、Windowsのbatファイルを作成して(macならshellスクリプト)、typescriptのコンパイルと一緒にしちゃう。(tscはバッチファイルなので、callで呼び出さないとchangeImport.pyが走らない)

buildTS.bat
@echo off
setlocal enabledelayedexpansion
cd %~dp0

REM [tsc is batch file. so call command needed]
call tsc -b ./

python changeImport.py

これで、buildTS.batを実行するだけでTypeScriptのコンパイル、importモジュール文の変換が一気にできてしまう!!!

NoiNoi

自作javascriptモジュールが読み込めない

jsファイルの中でimport を使っているので、type='module'として読み込みたいが、
下記のようなエラーが発生する。

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.

解決策

MIME typeを明示的に宣言する

import mimetypes
mimetypes.init()
mimetypes.add_type('application/javascript', '.js')

ここでMIME typeはapplication/javascriptでいいみたい。なぜかは分からん。