Share
Embed
LINE NEWS を TypeScript 化したい!/ How we did refactoring LINE NEWS codes into TypeScript
Akinori Inoue (LINE Corporation)
UIT meetup vol.8 online「We Are TypeScripters!」での発表資料です。
https://uit.connpass.com/event/161964/
https://cluster.mu/e/2623c783-862e-4004-a058-8d1c97b040cc
LINE Developers
March 18, 2020
Transcript
52 slides
-
井上明紀 フロントエンドエンジニア LINE 株式会社 UIT User Interface + Technologu team
@LINE corp 2019年新卒入社 趣味 -
LINE NEWS の開発 Planned release 開発のひとたち A B 1% 99%
開発人数もコード量も多い 2週に1回の頻度の高いリリース ABテストや機能の追加・削除が頻繁に行われる -
LINE NEWS の開発 Planned release 開発人数もコード量も多い 2週に1回の頻度の高いリリース ABテストや機能の追加・削除が頻繁に行われる A B
1% 99% 開発のひとたち キャッチアップが困難! -
LINE NEWS の品質保証 影響範囲 LINE NEWSのフロントエンド開発で良く耳にする言葉 コードの変更 QA確認 不具合修正 QA確認
不具合があれば 報告 QA: Quality Assurance -
変数のデータ構造が分からない! この props の item はどういう データを持つの? nullable? 機能改修が安全に行えているのか 自信がない
影響範囲大丈夫かな ... チームの声 -
% npm run eject など create-react-app の eject TS化にあたって Create
React App 依存から脱却 create-react-appに隠蔽されていたファイルが吐き出される webpack package.json Build Script Babel -
Eject した後のファイルを見直そう! 設定ファイルの見直し • 不要な設定の見直し • 古くなっていたパッケージの更新 ◦ webpack 3系
→ 4系 ◦ Babel 6系 → 7系 コードの見直し 環境変数として process.REACT_ENV を使用していた箇所の修正 -
• Development と Production の2つの設定ファイル • 細かい変更 ◦ dst のディレクトリやファイルの指定
◦ webpack-dev-server の設定 ◦ DefinePlugin による NODE_ENV の設定 webpack.cofig.js を書こう! webpack.config.js -
TypeScriptを扱うときの選択肢 es5 es5 + polyfill このどっちかでいける webpack.config.js webpack.cofig.js を書こう! tsc
webpack + ts-loader webpack + ts-loader + babel-loader webpack + babel-loader + @babel/preset-typescript -
tsc webpack + ts-loader TypeScriptを扱うときの選択肢 es5 es5 + polyfill webpack
+ ts-loader + babel-loader webpack + babel-loader + @babel/preset-typescript これを選択 webpack.config.js webpack.cofig.js を書こう! -
target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable 利用できる標準ライブラリの型 module es2015
出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) tscofig.json を書こう! compilerOptions tsconfig.json -
compilerOptions target target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable 利用できる標準ライブラリの型
module es2015 出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) tsconfig.json tscofig.json を書こう! -
compilerOptions lib target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable 利用できる標準ライブラリの型
module es2015 出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) 実行時の環境でサポートされていないと実行できない tsconfig.json tscofig.json を書こう! -
compilerOptions module target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable 利用できる標準ライブラリの型
module es2015 出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) tsconfig.json tscofig.json を書こう! -
compilerOptions allowJs target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable 利用できる標準ライブラリの型
module es2015 出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) tsconfig.json tscofig.json を書こう! -
jsファイルのある程度の型を推論 • 戻り値 • オブジェクト • 引数(引数を持たない場合のみ) 逆に一時的にundefinedを返している関数 等は.d.tsで正しく定義する必要あり jsをインポート
sample.js index.ts tsconfig.json compilerOptions allowJs tscofig.json を書こう! -
tsconfig.json compilerOptions jsx target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable
利用できる標準ライブラリの型 module es2015 出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) tscofig.json を書こう! -
tsconfig.json compilerOptions allowSyntheticDefaultImports target es5 出力するjsのesバージョン lib esnext, dom, dom.iterable
利用できる標準ライブラリの型 module es2015 出力するjsのモジュール管理方法 allowJs true JSの読み込みの許可と型の推論 jsx react 出力するjsのJSX記法への扱い allowSynthetic DefaultImports true export assignment を export defaultとして解釈 (ex. export = React;) tscofig.json を書こう! -
@babel/preset-env { "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3
}] ] } .babelrc 使ったプリセットは1つ .babelrc を書こう! -
.babelrc を書こう! const array = [1, 2, 3]; array.forEach(x =>
console.log(x)); import "core-js/modules/es.array.for-each"; var array = [1, 2, 3]; array.forEach(function (x) { return console.log(x); }); 必要に応じて core-js/modules 下をインポート 試しに @babel/cli でビルドしてみると ... babel-loader の場合は webpack が import を 解決するので不安であれば手動も可! .babelrc useBuiltIns: “usage” の挙動 -
• js と ts で CI で落とす基準を変更 • js だけ
deprecated な機能など warning が既に多数出ていたため許容 • ts では warning を許容せず厳しく適用 今までの LINE NEWS では • eslintrc はあったが warning は許容されていた .eslintrc .eslintrc.js を書こう! -
extendsプロパティ .eslintrc.js を書こう! .eslintrc • eslint:recommended • plugin:react/recommended • plugin:prettier/recommended
• prettier/react • plugin:@typescript-eslint/recommended • plugin:@typescript-eslint/eslint-recommended • prettier/@typescript-eslint -
extendsプロパティ JavaScript .eslintrc .eslintrc.js を書こう! • eslint:recommended • plugin:react/recommended •
plugin:prettier/recommended • prettier/react • plugin:@typescript-eslint/recommended • plugin:@typescript-eslint/eslint-recommended • prettier/@typescript-eslint -
extendsプロパティ JavaScript TypeScript .eslintrc .eslintrc.js を書こう! • eslint:recommended • plugin:react/recommended
• plugin:prettier/recommended • prettier/react • plugin:@typescript-eslint/recommended • plugin:@typescript-eslint/eslint-recommended • prettier/@typescript-eslint -
extendsプロパティ JavaScript • eslint:recommended • plugin:react/recommended • plugin:prettier/recommended • prettier/react
• plugin:@typescript-eslint/recommended • plugin:@typescript-eslint/eslint-recommended • prettier/@typescript-eslint TypeScript .eslintrc .eslintrc.js を書こう! -
rules: { 'react/jsx-uses-vars': 'warn', 'react/prop-types': 'off', 'react/no-string-refs': 'warn', // string
refs is deprecated 'react/no-deprecated': 'off', // deprecated methods 'react/display-name': 'warn', // Component's display name is necessary 'react/no-unescaped-entities': 'warn', // should be error 'react/jsx-key': 'warn', // should be error 'no-unused-vars': 'warn', // should be error 'no-redeclare': 'warn', // should be error 'no-async-promise-executor': 'warn', // should be error 'react/jsx-no-duplicate-props': 'warn', // should be error 'no-case-declarations': 'warn', 'no-prototype-builtins': 'warn', }, Prettierで全てfix! それでもエラーが発生する場合はwarnで許容 .eslintrc.js を書こう! .eslintrc -
jest.config.js を書こう! module.exports = { preset: "ts-jest", transform: { '^.+¥¥.(ts|js|tsx)$':
'ts-jest', }, setupFilesAfterEnv: ['./test/setupTests.ts'], }; jest.config.js -
module.exports = { preset: "ts-jest", transform: { '^.+¥¥.(ts|js|tsx)$': 'ts-jest', },
setupFilesAfterEnv: ['./test/setupTests.ts'], }; jest.config.js jest.config.js を書こう! tsのテストのために ts-jestを利用 -
module.exports = { preset: "ts-jest", transform: { '^.+¥¥.(ts|js|tsx)$': 'ts-jest', },
setupFilesAfterEnv: ['./test/setupTests.ts'], }; jest.config.js tsのテストのために ts-jestを利用 reactのユーティリティ (Enzyme)の設定など jest.config.js を書こう! -
• JSファイルは無理にTSに移行しない • 新規ファイルは必ずTSファイル • JSの変更箇所は影響範囲を考慮してTS移行 ◦ A.js → A.tsにフルで移行
◦ A.js + A.tsでモジュール単位で移行 ◦ A.js + A.d.ts .js → .ts のポリシー 影響範囲は新規や改修時のQA範囲と同じ or 少し増える程度 -
webpack.config.js tsconfig.json .babelrc eslintrc jest.config.js create-react-app を eject % npm
run eject 5つのコンフィグを作成 .js → .ts の移行ポリシーを作成 • JS ファイルは無理に TS に移行しない • 新規ファイルは必ず TS ファイル • JS の変更箇所は影響範囲を考慮して TS 移行