はじめに
~~コロナで家にいて暇だったので、~~初めてOSSを作って公開しました。
言語はTypeScript、環境はWebpack、IE11とCDNに対応、リポジトリはGithubです。
ブラウザ、nodejs、コマンドプロンプト、bashで動きます。
作ってみて、「これって実はこうなってたの?」と思ったポイントを共有します。
もし同じようなOSSの公開を検討されている方がおられましたら、ご参考いただきたくと思います。
OSSについて
OSS(オープンソースソフトウェア)は、ソースコードが公開され、誰でも利用、改良、修正、再配布ができるソフトウェアのことです。
もし作ったOSSに興味があればこちらの記事をご参考ください。
NLP(日本語)で使えるJSのDateライブラリを公開しました
https://qiita.com/ShotaOki/items/5e4b02f795fbf88bf0b1
CDNに登録する
たとえばjQueryを使いたいとき、htmlのヘッダにこんな風に書いていると思います。
<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
今回作成した僕のOSSでは、以下のように書けば取り込むことができます。
<script src="https://cdn.jsdelivr.net/gh/ShotaOki/NLPDate@v0.0.1/modern/nlpdate-main.min.js"></script>
このCDNに登録するには、どこにユーザー登録して、何をすればいいのでしょう。
実のところ、何もしなくても登録されます。
githubにタグが上がっていればCDNとして利用できます。
jsdelivrのURLはhttps://cdn.jsdelivr.net/gh/${ユーザー名}/${レポジトリ名}@${タグ名}/${ファイル名}
です。ghがgithub
のことです。タグ名にはlatest
と書いてもOKです。
# githubのメインブランチにタグを作る
git tag -a v0.0.1 -m 'リリースタグを作る'
# githubのメインブランチにタグをpushする
git push origin --tags
これでjsdelivrで使えるようになっています。
コマンドプロンプトでTypeScriptのファイルを動かす。
作ったOSSの都合で、どうしてもbashやコマンドプロンプトから動かしたいと思っていました。
REM 普通の使い方
nlp-date "明日の午後三時" -f "和暦の年月日時分秒"
>> 令和3年01月12日 15時00分00秒
REM 「明日」とか「今日」みたいにエポック秒を書けるので、ログを読むのに便利
nlp-date "1610341916の9時間後" -f "年月日時分秒"
>> 2021年01月11日 23時11分56秒
これはどうやれば実装できるのでしょう。
拡張子なしのJavaScriptファイルを作って、頭にShebang(#!で始まる行)を付けます。
#!/usr/bin/env node
// JavaScriptでソースを書けばよい
var NLPDate = require("../modern/nlpdate-main.min.js");
/**
中略:引数をパースする
*/
// 標準出力にconsole.logで出力する
console.log(NLPDate(argv["value"]).asString(argv["format"]));
頭にShebangがついていると、その環境で実行します。
コマンドプロンプトはShebangが読めないので、cmdを拡張子につけたファイルから呼び出します。
@ECHO off
REM nodeでJavaScriptファイル(nlp-date)を実行する
node "nlp-date" %*
EXIT /b %errorlevel%
このファイルの場所に環境変数を通せば、「nlp-date」コマンドが使えるようになります。
TypeScriptをIE11に対応する
IE11、フルネームで書くと_Internet Explorer 11_です。
TypeScripのts-loaderのままwebpackしても、過去の遺物 IE11で動きません。
開発元のMicrosoftがEdgeに移ったのだから、こちらとしても切り捨てたいところですが、さすがにWindowsに標準で入っているブラウザを切り捨てるわけにはいきません。
IE11向けのバンドルファイルの生成は、ts-loader -> babel-loaderの順で呼び出します。
こうすることで、IE11で対応していない関数(fetchとか)を作ってくれます。
{
rules: [
// JavaScriptをIE11向けにトランスパイルする
{
test: /\.(js|jsx|ts)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: ['> 1%', 'ie 11'],
useBuiltIns: 'usage',
corejs: 3,
},
],
],
},
},
},
// TypeScriptをJavascriptに変換する
{
test: /\.ts$/,
exclude: /(node_modules|bower_components)/,
loader: 'ts-loader',
options: {
configFile: 'babel.tsconfig.json', // <- babelの時だけtsconfig.jsonを変更
},
},
],
}
「module変数が見つからない」と言われたら、tsconfigのmoduleをes2015に書き換えます。
{
"includes": ["src/**/*.ts", "test/**/*.ts"],
"compilerOptions": {
"target": "es5",
"module": "es2015", // <- babelの時だけ"commonjs"から"es2015"に書き換える
// es2015だとブラウザ以外の実行(例:mochaの自動テスト)で失敗するので、
// webpackのoptionでbabelの時だけ変更する
"lib": ["es6", "es2019", "dom"]
}
}
ソースコード外にアロー関数が書かれる問題を解決するために、対応ブラウザを.browserlistrcに書きます。
> 1%
IE 11 // ここにIE 11を書けば、import文(ソースの外側)にアローが使われなくなる
not dead
これでトランスパイルすればTypeScriptのファイルがIE11対応されます。
ポリフィルも必要なものだけ取り込まれます。