Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LINE NEWS を TypeScript 化したい!/ How we did refact...

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
Tweet

More Decks by LINE Developers

Other Decks in Technology

Transcript

  1. LINE NEWS の開発 Planned release 開発のひとたち A B 1% 99%

    開発人数もコード量も多い 2週に1回の頻度の高いリリース ABテストや機能の追加・削除が頻繁に行われる
  2. % npm run eject など create-react-app の eject TS化にあたって Create

    React App 依存から脱却 create-react-appに隠蔽されていたファイルが吐き出される webpack package.json Build Script Babel
  3. Eject した後のファイルを見直そう! 設定ファイルの見直し • 不要な設定の見直し • 古くなっていたパッケージの更新 ◦ webpack 3系

    → 4系 ◦ Babel 6系 → 7系 コードの見直し 環境変数として process.REACT_ENV を使用していた箇所の修正
  4. • Development と Production の2つの設定ファイル • 細かい変更 ◦ dst のディレクトリやファイルの指定

    ◦ webpack-dev-server の設定 ◦ DefinePlugin による NODE_ENV の設定 webpack.cofig.js を書こう! webpack.config.js
  5. 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
  6. 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 を書こう!
  7. 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
  8. 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 を書こう!
  9. 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 を書こう!
  10. 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 を書こう!
  11. 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 を書こう!
  12. 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 を書こう!
  13. 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 を書こう!
  14. @babel/preset-env { "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3

    }] ] } .babelrc 使ったプリセットは1つ .babelrc を書こう!
  15. .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” の挙動
  16. • js と ts で CI で落とす基準を変更 • js だけ

    deprecated な機能など warning が既に多数出ていたため許容 • ts では warning を許容せず厳しく適用 今までの LINE NEWS では • eslintrc はあったが warning は許容されていた .eslintrc .eslintrc.js を書こう!
  17. 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
  18. 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
  19. 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
  20. 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 を書こう!
  21. 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
  22. jest.config.js を書こう! module.exports = { preset: "ts-jest", transform: { '^.+¥¥.(ts|js|tsx)$':

    'ts-jest', }, setupFilesAfterEnv: ['./test/setupTests.ts'], }; jest.config.js
  23. module.exports = { preset: "ts-jest", transform: { '^.+¥¥.(ts|js|tsx)$': 'ts-jest', },

    setupFilesAfterEnv: ['./test/setupTests.ts'], }; jest.config.js jest.config.js を書こう! tsのテストのために ts-jestを利用
  24. 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 を書こう!
  25. • JSファイルは無理にTSに移行しない • 新規ファイルは必ずTSファイル • JSの変更箇所は影響範囲を考慮してTS移行 ◦ A.js → A.tsにフルで移行

    ◦ A.js + A.tsでモジュール単位で移行 ◦ A.js + A.d.ts .js → .ts のポリシー 影響範囲は新規や改修時のQA範囲と同じ or 少し増える程度
  26. 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 移行