Anúncio
Anúncio

Mais conteúdo relacionado

Apresentações para você(20)

Similar a react-scriptsはwebpackで何をしているのか(20)

Anúncio

Último(20)

Anúncio

react-scriptsはwebpackで何をしているのか

  1. react‑scriptsはwebpackで何をしているのか 2019.01.28.三宅暁
  2. 自己紹介 三宅暁(AKIRA‑MIYAKE) BizteX株式会社開発部デザインチーム フロントエンドリードプログラマー JavaScript/HTML/CSS(React/Angular/Vue.js) UIデザイン(ツール系が得意) UXデザイン(最近データ分析でRを使い始めました) サーバレスアーキテクチャ アカウント GitHub:AKIRA‑MIYAKE Twitter:AKIRA@DreamOfEleCat ブログ:DreamofElectricCat
  3. 今日話すこと create‑react‑appが利用しているreact‑scriptは、webpackで何をしているのか eject コマンドで挿入される設定ファイル群はreact‑scriptのものなので、設定を 変更するときの参考に
  4. 対象 create‑react‑app/packages/react‑scripts/の config/webpack.config.js eject コマンドで追加されるのもこのファイル 最近の変更(Mergewebpackconfiguration#5722)で単一のファイルに統合された
  5. publicPath と publicUrl const publicPath = isEnvProduction ? paths.servedPath : isEnvDevelopment && '/'; const shouldUseRelativeAssetPaths = publicPath === './'; const publicUrl = isEnvProduction ? publicPath.slice(0, -1) : isEnvDevelopment && ''; ビルドしたファイル群がどこにデプロイされるか 開発時は相対パス index.html やcssファイルのコンテンツへのパスの制御 publicPath のデフォルトはWebサーバのルートディレクトリ publicUrl のデフォルトは空文字 共に config/paths.js で定義
  6. getStyleLoaders const getStyleLoaders = (cssOptions, preProcessor) => { ... return loaders; }; cssのローダーを返す関数 開発時は style-loader を、ビルド時は MiniCssExtractPlugin を適用 ビルド時はcssファイルが生成される postcss-loader の options でpostcssのプラグイン等を設定 preProcessor (sass‑loaderとか)が渡された場合、loadersに追加
  7. entry [ isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'), paths.appIndexJs, ] 開発時は react-dev-utils/webpackHotDevClient.js を追加 WebpackDevServerにsocket接続するためのclient
  8. output devtoolModuleFilenameTemplate { devtoolModuleFilenameTemplate: isEnvProduction ? info => path .relative(paths.appSrc, info.absoluteResourcePath) .replace(//g, '/') : isEnvDevelopment && (info => path.resolve(info.absoluteResourcePath).replace(//g, '/')), } source‑mapの出力先の変換 ビルド時はsrcディレクトリをベースとした相対パスを解決 jsフォルダ内にsrcディレクトと同じ構成に見えるように 開発時はローカルの絶対パスに変換 プロジェクトのディレクトリ構成と同じように見えるように
  9. optimization TerserPlugin new TeserPlugin({ parse: { ecma: 8 }, compress: { ecma: 5 }, mangle: { safari10: true }, output: { ecma: 5 }, }) webpack-contrib/terser-webpack-plugin を利用 パースはECMA8を適用するが、無効なコードへの変換を防ぐために圧縮と出 力ではECMA5を適用している Safari10/11におけるloop内のスコープと await のバグのワークアラウンド の追加
  10. resolve modules { modules: ['node_modules'].concat( process.env.NODE_PATH.split(path.delimiter).filter(Boolean) ), } webpackが探索する node_modules の追加 プロジェクトの node_modules を優先するために、2番目に追加される
  11. resolve plugins [ PnpWebpackPlugin, new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), ] pnp-webpack-plugin の追加 yarnのPlug'n'Playを利用するためのプラグイン react-dev-utils/ModuleScopePlugin.js の追加 node_modules 以外の src ディレクトリ外部のモジュールへの依存を防止 するプラグイン
  12. module strictExportPresence { strictExportPresence: true } エクスポートが不足している場合にエラーにする
  13. module.rules requireEnsure { parser: { requireEnsure: false } }, 標準仕様にない require.ensure を無効化
  14. module.rules eslint-loader 通常のloaderの前に実行 eslintの設定として eslint-config-react-app を指定 formatterに react-dev-utils/eslintFormatter を指定 eslintの出力をcreate‑react‑appのコンソールに統合 { test: /.(js|mjs|jsx)$/, enforce: 'pre', use: [ { options: { formatter: require.resolve('react-dev-utils/eslintFormatter'), eslintPath: require.resolve('eslint'), baseConfig: { extends: [require.resolve('eslint-config-react-app')] }, ignore: false, useEslintrc: false, }, loader: require.resolve('eslint-loader'), }, ], include: paths.appSrc, }
  15. mdoule.rules babel-loader (src内のファイルを対象) { test: /.(js|mjs|jsx|ts|tsx)$/, include: paths.appSrc, loader: require.resolve('babel-loader'), options: { customize: require.resolve( 'babel-preset-react-app/webpack-overrides' ), babelrc: false, configFile: false, presets: [require.resolve('babel-preset-react-app')], plugins: [ [ require.resolve('babel-plugin-named-asset-import'), { loaderMap: { svg: { ReactComponent: '@svgr/webpack?-svgo![path]', }, }, }, ], ], }, }
  16. mdoule.rules babel-loader (src内のファイルを対象) プリセットとして babel-preset-react-app を指定 babel-plugin-named-asset-import がプラグインに追加される SVGファイルをReactコンポーネントとして扱うためのプラグイン babel-preset-react-app/webpack-overrides.js を babel-loader の customize に設定 BabelMacrosのキャッシュをいい感じにハンドリングしてくれる
  17. babel-preset-react-app babel-preset-react-app/create.js で定義が行われている 以下のパッケージがデフォルトで含まれる @babel/preset-env / @babel/preset-react / babel-plugin-macros / @babel/plugin-transform-destructuring / @babel/plugin- proposal-class-properties / @babel/plugin-proposal-object-rest- spread / @babel/plugin-transform-runtime / @babel/plugin- syntax-dynamic-import TypeScriptが有効な時に追加されるもの @babel/preset-typescript / @babel/plugin-proposal-decorators flowが有効な時に追加されるもの @babel/plugin-transform-flow-strip-types ビルド時に追加されるもの babel-plugin-transform-react-remove-prop-types テスト時に追加されるもの babel-plugin-dynamic-import-node
  18. mdoule.rules babel-loader (src外のファイルを対象) { test: /.(js|mjs)$/, exclude: /@babel(?:/|{1,2})runtime/, loader: require.resolve('babel-loader'), options: { presets: [ [ require.resolve('babel-preset-react-app/dependencies'), { helpers: true }, ], ], }, } プリセットとして babel-preset-react-app/dependencies.js を指定 @babel/runtime 以外の依存パッケージをトランスパイルする
  19. mdoule.rules css(グローバル) { test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction && shouldUseSourceMap, }), } cssRegex は /.css$/ cssModuleRegex の /.module.css$/ に該当するファイルは除外 getStyleLoaders 関数でローダを取得
  20. mdoule.rules css(モジュール) { test: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdentm }), } cssModuleRegex の /.module.css$/ に該当するファイルに適用される css‑loaderの modules オプションを有効にしている getLocalIdent はcssのクラス名の生成方法を指定するオプション react-dev-utils/getCSSModuleLocalIdent.js を利用
  21. module.rules sass { test: sassRegex, exclude: sassModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, }, 'sass-loader' ), }, { test: sassModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdent, }, 'sass-loader' ), } 基本的にcssと同様でpreProsessorとして sass-loader を指定
  22. plugins InterpolateHtmlPlugin new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw) react-dev-utils/InterpolateHtmlPlugin.js を追加 HtmlWebpackPluginの処理の後に、 index.html の変数定義の部分を env.raw の値で置き換える
  23. plugins ModuleNotFoundPlugin new ModuleNotFoundPlugin(paths.appPath) react-dev-utils/ModuleNotFoundPlugin.js を追加 インポートするモジュールが見つからなかった場合のエラーメッセージを制御
  24. plugins WatchMissingNodeModulesPlugin isEnvDevelopment && new WatchMissingNodeModulesPlugin(paths.appNodeModules) 開発時に react-dev-utils/WatchMissingNodeModulesPlugin を追加 依存ライブラリがインストールされていない場合に、強制的にインストール
  25. plugins WorkboxWebpackPlugin isEnvProduction && new WorkboxWebpackPlugin.GenerateSW({ clientsClaim: true, exclude: [/.map$/, /asset-manifest.json$/], importWorkboxFrom: 'cdn', navigateFallback: publicUrl + '/index.html', navigateFallbackBlacklist: [ new RegExp('^/_'), new RegExp('/[^/]+.[^/]+$'), ], }) ビルド時に workbox-webpack-plugin を追加 Workbox はWebアプリケーションのオフラインサポートを追加するGoogleの JavaScriptライブラリ 詳しくは workbox-webpack-plugin の公式ページを参照 react-scripts/template/src/serviceWorker.js の register() で登録す ることで、静的ファイルのプリキャッシュを行うことができる
  26. plugins ForkTsCheckerWebpackPlugin useTypeScript && new ForkTsCheckerWebpackPlugin({ tsconfig: paths.appTsConfig, formatter: typescriptFormatter, }) Realytics/fork-ts-checker-webpack-plugin を追加 別プロセスでTypeScriptの型チェックを実行 TypeScriptの利用は tsconfig.json の有無で判定される formatterに react-dev-utils/typescriptFormatter.js を指定 プラグインの出力をcreate‑react‑appのコンソールに統合
Anúncio