TypeScript+webpackでブラウザでもNodeでも動くライブラリを作るメモ
ブラウザで動く事は確認したけど、Node環境でうまくいくかの動作検証はできてない状態
概要
webpackを使ってTypeScriptで書かれたライブラリをブラウザ向け、もしくはNode向けにバンドルしようと思ってあれこれしてみた備忘録
webpack.config.jsでoutputの設定をごにょごにょするだけでもある程度行けるが
型定義ファイルとかちゃんと用意しようとすると一筋縄ではいかなかったので
そのあたりについて記載する。
入れたパッケージは以下 - webpack - webpack-cli - typescript - ts-loader
webpack.config.json
とりあえずwebpack.config.js
の中身
const path = require('path'); //----------------------------------------------------------------------------- // コマンドライン引数には以下の値を指定する // --mode: development or production // --type: browser or node //----------------------------------------------------------------------------- module.exports = (env, argv) => { // コマンドライン引数による判定 const mode = (argv.mode === undefined)? "production" : "development"; const isDev = mode === "development"; const type="node"; // ブラウザ用の設定 const browser = { path: path.join(__dirname, '/browser'), filename: (isDev)? "mylib.js":"mylib.min.js", configFile: "tsconfig.json", }; // Node環境用の設定 const node = { path: path.join(__dirname, "/dist"), filename:"index.js", configFile: "tsconfig.node.json" }; // argv.typeにはbrowserかnodeのどちらかを指定する。指定しないと多分エラーになる const params = {browser, node}[argv.type]; console.log(params); const conf = { mode: mode, entry: './src/index.ts', output: { path: params.path, publicPath: '/', filename: params.filename, library: 'MyLib', libraryExport: '', libraryTarget: 'umd', globalObject: 'this', }, module: { rules: [{ test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { configFile: params.configFile } } ] }] }, // import 文で .ts ファイルを解決するため // これを定義しないと import 文で拡張子を書く必要が生まれる。 // フロントエンドの開発では拡張子を省略することが多いので、 // 記載したほうがトラブルに巻き込まれにくい。 resolve: { // 拡張子を配列で指定 extensions: [ '.ts', '.js', ], } } // 開発時のみ if (isDev) { conf.devtool = 'inline-source-map'; } return conf; }
まずコマンドライン引数でwebpack --mode development --type browser
って感じで
modeとtypeを受け取るようにした。
この引数の内容を見て、webpackの設定を切り替えるようにしている。
outputの設定
output: { path: params.path, publicPath: '/', filename: params.filename, library: 'MyLib', libraryExport: '', libraryTarget: 'umd', globalObject: 'this', },
path
は出力先のフォルダで
type
にbrowser
が指定された場合は./browser
にtype
にnode
が指定された場合は./dist
に
コンパイルしたファイルを出力するようにした。
filename
に関しては
ブラウザ向けの場合、開発時はmylib.js
、製品版はmylib.min.js
となるようにし
Node向けの場合はindex.js
というファイルが生成されるようにした。
library
に関してはライブラリを作るときにそれっぽい名前にし
libraryTarget: 'umd', globalObject: 'this',
この設定をしておくことでブラウザでも動作するようにコンパイルされる。
Node向けにビルドする際に.d.ts
とかを出す
型定義ファイルを出力するにはtsconfig.json
の設定が必要だった。
{ "compilerOptions": { "declaration": true, "declarationMap": true, } }
このdeclaration
とdeclarationMap
をtrue
に指定すれば型定義ファイルやマップファイルが出力されるが
これはブラウザ向けの場合は不要なのでtsconfig.json
を2種類用意した。
tsconfig.json
{ "compilerOptions": { "target": "es5", "module": "es2015", "rootDir": "./src", "strict": true, "moduleResolution": "node", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true } }
tsconfig.node.json
{ "extends": "./tsconfig.json", "compilerOptions": { "declaration": true, /* Generates corresponding '.d.ts' file. */ "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ "outDir": "./dist", /* Redirect output structure to the directory. */ } }
ブラウザ向けビルドの時はtsconfig.json
が適用され、Node向けビルドの時はtsconfig.node.json
が適用されるようにwebpack.config.js
の以下の部分に細工している
module: { rules: [{ test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { configFile: params.configFile } } ] }] },
ts-loader
のオプションで適用するコンフィグファイルを指定できるので、ここでコマンドライン引数のtype
で判定して、適用するコンフィグファイルを変更している。
※tsconfig.node.json
のoutDir
の指定について
型定義ファイルはoutDir
で指定した場所に出力されるので指定している。
これでビルドした結果は予想通りの動きになっていていい感じだ。
ビルドされたjsはブラウザではうまいこと動いている。
あとはこれで作成したものが、他のNodeプロジェクトにインストールしてうまく動くかどうか。