- create-react-appが利用しているreact-scriptは、webpackで何をしているのか
eject
コマンドで挿入される設定ファイル群はreact-scriptのものなので、設定を変更するときの参考に
対象
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
を適用
postcss-loader
の options
でpostcssのプラグイン等を設定
preProcessor
(sass-loaderとか) が渡された場合、loadersに追加
entry
[
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
]
output
devtoolModuleFilenameTemplate
{
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
}
optimization
TerserPlugin
new TeserPlugin({
parse: { ecma: 8 },
compress: { ecma: 5 },
mangle: { safari10: true },
output: { ecma: 5 },
})
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]),
]
module
strictExportPresence
{ strictExportPresence: true }
module.rules
requireEnsure
{ parser: { requireEnsure: false } },
- 標準仕様にない
require.ensure
を無効化
module.rules
eslint-loader
{
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-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 },
],
],
},
}
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のクラス名の生成方法を指定するオプション
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)
plugins
ModuleNotFoundPlugin
new ModuleNotFoundPlugin(paths.appPath)
plugins
WatchMissingNodeModulesPlugin
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules)
plugins
WorkboxWebpackPlugin
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
new RegExp('^/_'),
new RegExp('/[^/]+\\.[^/]+$'),
],
})
plugins
ForkTsCheckerWebpackPlugin
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
tsconfig: paths.appTsConfig,
formatter: typescriptFormatter,
})