"use strict";
const path = require("path");
const fs = require("fs");
const getPublicUrlOrPath = require("react-dev-utils/getPublicUrlOrPath");
// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served.
// webpack needs to know it to put the right <script> hrefs into HTML even in
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
const publicUrlOrPath = getPublicUrlOrPath(
process.env.NODE_ENV === "development",
require(resolveApp("package.json")).homepage,
process.env.PUBLIC_URL
);
const buildPath = process.env.BUILD_PATH || "build";
const moduleFileExtensions = [
"web.mjs",
"mjs",
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
];
// Resolve file paths in the same order as webpack
const resolveModule = (resolveFn, filePath) => {
const extension = moduleFileExtensions.find((extension) =>
fs.existsSync(resolveFn(`${filePath}.${extension}`))
);
if (extension) {
return resolveFn(`${filePath}.${extension}`);
}
return resolveFn(`${filePath}.js`);
};
// config after eject: we're in ./config/
module.exports = {
dotenv: resolveApp(".env"),
appPath: resolveApp("."),
appBuild: resolveApp(buildPath),
appPublic: resolveApp("public"),
appHtml: resolveApp("public/index.html"),
appIndexJs: resolveModule(resolveApp, "src/index"),
appPackageJson: resolveApp("package.json"),
appSrc: resolveApp("src"),
appTsConfig: resolveApp("tsconfig.json"),
appJsConfig: resolveApp("jsconfig.json"),
yarnLockFile: resolveApp("yarn.lock"),
testsSetup: resolveModule(resolveApp, "src/setupTests"),
proxySetup: resolveApp("src/setupProxy.js"),
appNodeModules: resolveApp("node_modules"),
swSrc: resolveModule(resolveApp, "src/service-worker"),
ssrIndexJs: resolveApp("src/index.server.js"),
ssrBuild: resolveApp("dist"),
publicUrlOrPath,
};
module.exports.moduleFileExtensions = moduleFileExtensions;
ssrIndexJs: resolveApp("src/index.server.js"),
// 서버사이드 렌더링 엔트리
ssrBuild: resolveApp("dist"),
//웹팩 처리 후 저장 경로
const paths = require("./paths");
const getCSSModuleLocalIndent = require("react-dev-utils/getCSSModuleLocalIdent");
const nodeExternals = require("webpack-node-externals");
const webpack = require("webpack");
const getClientEnvironment = require("./env");
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
module.exports = {
mode: "production",
entry: paths.ssrIndexJs,
target: "node",
output: {
path: paths.ssrBuild,
filename: "server.js",
chunkFilename: "js/[name].chunk.js",
publicPath: paths.publicUrlOrPath,
},
module: {
rules: [
{
oneOf: [
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve("babel-loader"),
options: {
customize: require.resolve(
"babel-preset-react-app/webpack-overrides"
),
presets: [
[
require.resolve("babel-preset-react-app"),
{
runtime: "automatic",
},
],
],
plugins: [
[
require.resolve("babel-plugin-named-asset-import"),
{
loaderMap: {
svg: {
ReactComponent:
"@svgr/webpack?-svgo,+titleProp,+ref![path]",
},
},
},
],
],
cacheDirectory: true,
cacheCompression: false,
compact: false,
},
},
{
test: cssRegex,
exclude: cssModuleRegex,
loader: require.resolve("css-loader"),
options: {
importLoaders: 1,
modules: {
exportOnlyLocals: true,
},
},
},
{
test: cssModuleRegex,
loader: require.resolve("css-loader"),
options: {
importLoaders: 1,
modules: {
exportOnlyLocals: true,
getLocalIdent: getCSSModuleLocalIndent,
},
},
},
{
test: sassRegex,
exclude: sassModuleRegex,
use: [
{
loader: require.resolve("css-loader"),
options: {
importLoaders: 3,
modules: {
exportOnlyLocals: true,
getLocalIdent: getCSSModuleLocalIndent,
},
},
},
require.resolve("sass-loader"),
],
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve("url-loader"),
options: {
emitFile: false,
limit: 10000,
name: "static/media/[name].[hash:8].[ext]",
},
},
{
loader: require.resolve("file-loader"),
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
emitFile: false,
name: "static/media/[name].[hash:8].[ext]",
},
},
],
},
],
},
resolve: {
modules: ["node_modules"],
},
externals: [
nodeExternals({
allowlist: [/@babel/],
}),
],
};
eject하기
콘솔:
git add .
git commit -m'Commit before eject'
yarn eject
config/webpack.config.server.js 파일 작성하기
node_modules에서 불러오는 것 제외하고 번들링하기
콘솔 : yarn add webpack-node-externals
설정 적용: webpack.config.server.js의 상단에
'const nodeExternals = require('webpack-node-externals'); ' , modules 설정 적기
빌드 스크립트 작성하기
process.env.BABEL_ENV = "production";
process.env.NODE_ENV = "production";
process.on("unhandledRejection", (err) => {
throw err;
});
require("../config/env");
const fs = require("fs-extra");
const webpack = require("webpack");
const config = require("../config/webpack.config.server");
const paths = require("../config/paths");
function build() {
console.log("Creating server build..");
fs.emptyDirSync(paths.ssrBuild);
let compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err) {
console.log(err);
return;
}
console.log(stats.toString());
});
});
}
build();
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"start:server": "node dist/server.js",
"build:server": "node scripts/build.server.js"
},