SlideShare a Scribd company logo
react‑scriptsはwebpackで何をしているのか
2019.01.28.三宅暁
自己紹介
三宅暁(AKIRA‑MIYAKE)
BizteX株式会社開発部デザインチーム
フロントエンドリードプログラマー
JavaScript/HTML/CSS(React/Angular/Vue.js)
UIデザイン(ツール系が得意)
UXデザイン(最近データ分析でRを使い始めました)
サーバレスアーキテクチャ
アカウント
GitHub:AKIRA‑MIYAKE
Twitter:AKIRA@DreamOfEleCat
ブログ:DreamofElectricCat
今日話すこと
create‑react‑appが利用しているreact‑scriptは、webpackで何をしているのか
eject コマンドで挿入される設定ファイル群はreact‑scriptのものなので、設定を
変更するときの参考に
対象
create‑react‑app/packages/react‑scripts/の config/webpack.config.js
eject コマンドで追加されるのもこのファイル
最近の変更(Mergewebpackconfiguration#5722)で単一のファイルに統合された
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 で定義
getStyleLoaders
const getStyleLoaders = (cssOptions, preProcessor) => {
...
return loaders;
};
cssのローダーを返す関数
開発時は style-loader を、ビルド時は MiniCssExtractPlugin を適用
ビルド時はcssファイルが生成される
postcss-loader の options でpostcssのプラグイン等を設定
preProcessor (sass‑loaderとか)が渡された場合、loadersに追加
entry
[
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
]
開発時は react-dev-utils/webpackHotDevClient.js を追加
WebpackDevServerにsocket接続するためのclient
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ディレクトと同じ構成に見えるように
開発時はローカルの絶対パスに変換
プロジェクトのディレクトリ構成と同じように見えるように
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 のバグのワークアラウンド
の追加
resolve
modules
{
modules: ['node_modules'].concat(
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
}
webpackが探索する node_modules の追加
プロジェクトの node_modules を優先するために、2番目に追加される
resolve
plugins
[
PnpWebpackPlugin,
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
]
pnp-webpack-plugin の追加
yarnのPlug'n'Playを利用するためのプラグイン
react-dev-utils/ModuleScopePlugin.js の追加
node_modules 以外の src ディレクトリ外部のモジュールへの依存を防止
するプラグイン
module
strictExportPresence
{ strictExportPresence: true }
エクスポートが不足している場合にエラーにする
module.rules
requireEnsure
{ parser: { requireEnsure: false } },
標準仕様にない require.ensure を無効化
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,
}
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]',
},
},
},
],
],
},
}
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のキャッシュをいい感じにハンドリングしてくれる
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
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 以外の依存パッケージをトランスパイルする
mdoule.rules
css(グローバル)
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
}
cssRegex は /.css$/
cssModuleRegex の /.module.css$/ に該当するファイルは除外
getStyleLoaders 関数でローダを取得
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 を利用
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 を指定
plugins
InterpolateHtmlPlugin
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw)
react-dev-utils/InterpolateHtmlPlugin.js を追加
HtmlWebpackPluginの処理の後に、 index.html の変数定義の部分を env.raw
の値で置き換える
plugins
ModuleNotFoundPlugin
new ModuleNotFoundPlugin(paths.appPath)
react-dev-utils/ModuleNotFoundPlugin.js を追加
インポートするモジュールが見つからなかった場合のエラーメッセージを制御
plugins
WatchMissingNodeModulesPlugin
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules)
開発時に react-dev-utils/WatchMissingNodeModulesPlugin を追加
依存ライブラリがインストールされていない場合に、強制的にインストール
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() で登録す
ることで、静的ファイルのプリキャッシュを行うことができる
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のコンソールに統合

More Related Content

What's hot (20)

PDF
Amplify Studioを使ってみた
虎の穴 開発室
 
PDF
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
Kouhei Sutou
 
PDF
Kubernetesの良さを活かして開発・運用!Cloud Native入門 / An introductory Cloud Native #osc19tk
whywaita
 
PDF
Apache Airflow入門 (マーケティングデータ分析基盤技術勉強会)
Takeshi Mikami
 
PDF
KafkaとAWS Kinesisの比較
Yoshiyasu SAEKI
 
PDF
20190213 AWS Black Belt Online Seminar Amazon SageMaker Advanced Session
Amazon Web Services Japan
 
PDF
Infrastructure as Code (IaC) 談義 2022
Amazon Web Services Japan
 
PDF
What's new in Spring Boot 2.6 ?
土岐 孝平
 
PDF
Docker Compose 徹底解説
Masahito Zembutsu
 
PPTX
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
NTT DATA Technology & Innovation
 
PPTX
Dockerからcontainerdへの移行
Akihiro Suda
 
PDF
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
apkiban
 
PDF
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
PDF
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
yoku0825
 
PDF
Mavenの真実とウソ
Yoshitaka Kawashima
 
PDF
Ansible でお世話になっている機能と拡張
akira6592
 
PDF
ふつうの受託開発チームのつくりかた
Yoshitaka Kawashima
 
PDF
こわくない Git
Kota Saito
 
PDF
Micrometer/Prometheusによる大規模システムモニタリング #jsug #sf_26
Yahoo!デベロッパーネットワーク
 
PPTX
え、毎月手作業でレポートを作ってるの?Power BI を使えば自動化できますよ!
Yugo Shimizu
 
Amplify Studioを使ってみた
虎の穴 開発室
 
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
Kouhei Sutou
 
Kubernetesの良さを活かして開発・運用!Cloud Native入門 / An introductory Cloud Native #osc19tk
whywaita
 
Apache Airflow入門 (マーケティングデータ分析基盤技術勉強会)
Takeshi Mikami
 
KafkaとAWS Kinesisの比較
Yoshiyasu SAEKI
 
20190213 AWS Black Belt Online Seminar Amazon SageMaker Advanced Session
Amazon Web Services Japan
 
Infrastructure as Code (IaC) 談義 2022
Amazon Web Services Japan
 
What's new in Spring Boot 2.6 ?
土岐 孝平
 
Docker Compose 徹底解説
Masahito Zembutsu
 
PostgreSQLのロール管理とその注意点(Open Source Conference 2022 Online/Osaka 発表資料)
NTT DATA Technology & Innovation
 
Dockerからcontainerdへの移行
Akihiro Suda
 
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
apkiban
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
yoku0825
 
Mavenの真実とウソ
Yoshitaka Kawashima
 
Ansible でお世話になっている機能と拡張
akira6592
 
ふつうの受託開発チームのつくりかた
Yoshitaka Kawashima
 
こわくない Git
Kota Saito
 
Micrometer/Prometheusによる大規模システムモニタリング #jsug #sf_26
Yahoo!デベロッパーネットワーク
 
え、毎月手作業でレポートを作ってるの?Power BI を使えば自動化できますよ!
Yugo Shimizu
 

More from 暁 三宅 (6)

PDF
AWSで開発するサーバレスAPIバックエンド
暁 三宅
 
PDF
何を自動化するのか
暁 三宅
 
PDF
サーバレスアーキテクチャを実戦投入するにあたって知るべきこと
暁 三宅
 
PDF
Angular2 + AWS Lambdaでサーバサイドレンダリングしてみた
暁 三宅
 
PDF
フロントエンドの設計に関する考察
暁 三宅
 
PDF
Apple watchアプリを作ってみた
暁 三宅
 
AWSで開発するサーバレスAPIバックエンド
暁 三宅
 
何を自動化するのか
暁 三宅
 
サーバレスアーキテクチャを実戦投入するにあたって知るべきこと
暁 三宅
 
Angular2 + AWS Lambdaでサーバサイドレンダリングしてみた
暁 三宅
 
フロントエンドの設計に関する考察
暁 三宅
 
Apple watchアプリを作ってみた
暁 三宅
 
Ad

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