[WIP] nextjs build-app.sh #953
@ -1,16 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||
set -euo pipefail
|
||||
|
||||
if [ -n "${CERC_SCRIPT_DEBUG:-}" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
CERC_MIN_NEXTVER=13.4.2
|
||||
CERC_DEFAULT_WEBPACK_VER="5.93.0"
|
||||
|
||||
CERC_NEXT_VERSION="${CERC_NEXT_VERSION:-keep}"
|
||||
CERC_WEBPACK_VERSION="${CERC_WEBPACK_VERSION:-keep}"
|
||||
|
||||
CERC_BUILD_TOOL="${CERC_BUILD_TOOL}"
|
||||
# Determine the build tool
|
||||
CERC_BUILD_TOOL="${CERC_BUILD_TOOL:-}"
|
||||
if [ -z "$CERC_BUILD_TOOL" ]; then
|
||||
if [ -f "pnpm-lock.yaml" ]; then
|
||||
CERC_BUILD_TOOL=pnpm
|
||||
@ -23,11 +20,36 @@ if [ -z "$CERC_BUILD_TOOL" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
||||
WORK_DIR="${1:-/app}"
|
||||
|
||||
cd "${WORK_DIR}" || exit 1
|
||||
|
||||
# Get the app's Next.js version
|
||||
CERC_NEXT_VERSION=$(jq -r '.dependencies.next' package.json)
|
||||
echo "Using Next.js version: $CERC_NEXT_VERSION"
|
||||
|
||||
# Determine webpack version based on Next.js version (unused if already installed)
|
||||
determine_webpack_version() {
|
||||
local next_version=$1
|
||||
local major_version=${next_version%%.*}
|
||||
case $major_version in
|
||||
13)
|
||||
echo "5.75.0"
|
||||
;;
|
||||
14)
|
||||
echo "5.88.0"
|
||||
;;
|
||||
*)
|
||||
echo "5.93.0" # Default to latest stable version if unknown
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION")
|
||||
echo "Using webpack version: $CERC_WEBPACK_VERSION"
|
||||
|
||||
# Determine the Next.js config file
|
||||
if [ -f "next.config.mjs" ]; then
|
||||
NEXT_CONFIG_JS="next.config.mjs"
|
||||
IMPORT_OR_REQUIRE="import"
|
||||
@ -41,203 +63,142 @@ if [ ! -f "${NEXT_CONFIG_JS}" ]; then
|
||||
touch ${NEXT_CONFIG_JS}
|
||||
fi
|
||||
|
||||
# Backup the original config if not already done
|
||||
if [ ! -f "next.config.dist" ]; then
|
||||
cp $NEXT_CONFIG_JS next.config.dist
|
||||
cp "$NEXT_CONFIG_JS" next.config.dist
|
||||
fi
|
||||
|
||||
which js-beautify >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
npm i -g js-beautify
|
||||
fi
|
||||
# Install js-beautify if not present
|
||||
command -v js-beautify >/dev/null || npm i -g js-beautify
|
||||
|
||||
# js-beautify formats NEXTJS_CONFIG_FILE (ie next.config.js / next.config.mjs) so we can reliably transformable later
|
||||
js-beautify next.config.dist > ${NEXT_CONFIG_JS}
|
||||
echo "" >> ${NEXT_CONFIG_JS}
|
||||
# Beautify the config file
|
||||
js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty"
|
||||
mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS"
|
||||
|
||||
if [ "${IMPORT_OR_REQUIRE}" == "require" ]; then
|
||||
WEBPACK_REQ_LINE=$(grep -n "require([\'\"]webpack[\'\"])" ${NEXT_CONFIG_JS} | cut -d':' -f1)
|
||||
if [ -z "$WEBPACK_REQ_LINE" ]; then
|
||||
cat > ${NEXT_CONFIG_JS}.0 <<EOF
|
||||
const webpack = require('webpack');
|
||||
EOF
|
||||
# Add webpack import/require if not present
|
||||
if [ "$IMPORT_OR_REQUIRE" = "import" ]; then
|
||||
if ! grep -q "import.*webpack" "$NEXT_CONFIG_JS"; then
|
||||
sed -i '1iimport webpack from "webpack";' "$NEXT_CONFIG_JS"
|
||||
fi
|
||||
if ! grep -q "import.*createRequire" "$NEXT_CONFIG_JS"; then
|
||||
sed -i '2iimport { createRequire } from "module";\nconst require = createRequire(import.meta.url);' "$NEXT_CONFIG_JS"
|
||||
fi
|
||||
else
|
||||
WEBPACK_IMPORT_LINE=$(grep -n "^import .*[\'\"]webpack[\'\"];?$" ${NEXT_CONFIG_JS} | cut -d':' -f1)
|
||||
if [ -z "$WEBPACK_IMPORT_LINE" ]; then
|
||||
cat > ${NEXT_CONFIG_JS}.0 <<EOF
|
||||
import webpack from 'webpack';
|
||||
EOF
|
||||
fi
|
||||
CREATE_REQUIRE_LINE=$(grep -n "require = createRequire" ${NEXT_CONFIG_JS} | cut -d':' -f1)
|
||||
if [ -z "$CREATE_REQUIRE_LINE" ]; then
|
||||
cat >> ${NEXT_CONFIG_JS}.0 <<EOF
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
EOF
|
||||
if ! grep -q "require.*webpack" "$NEXT_CONFIG_JS"; then
|
||||
sed -i '1iconst webpack = require("webpack");' "$NEXT_CONFIG_JS"
|
||||
fi
|
||||
fi
|
||||
|
||||
cat > ${NEXT_CONFIG_JS}.1 <<EOF
|
||||
# Add environment mapping logic if not present
|
||||
if ! grep -q "let envMap;" "$NEXT_CONFIG_JS"; then
|
||||
cat << 'EOF' >> "$NEXT_CONFIG_JS"
|
||||
|
||||
let envMap;
|
||||
try {
|
||||
// .env-list.json provides us a list of identifiers which should be replaced at runtime.
|
||||
envMap = require('./.env-list.json').reduce((a, v) => {
|
||||
a[v] = \`"CERC_RUNTIME_ENV_\${v.split(/\./).pop()}"\`;
|
||||
a[v] = JSON.stringify(`CERC_RUNTIME_ENV_${v.split(/\./).pop()}`);
|
||||
return a;
|
||||
}, {});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
// If .env-list.json cannot be loaded, we are probably running in dev mode, so use process.env instead.
|
||||
console.error('Error loading .env-list.json:', e);
|
||||
envMap = Object.keys(process.env).reduce((a, v) => {
|
||||
if (v.startsWith('CERC_')) {
|
||||
a[\`process.env.\${v}\`] = JSON.stringify(process.env[v]);
|
||||
a[`process.env.${v}`] = JSON.stringify(process.env[v]);
|
||||
}
|
||||
return a;
|
||||
}, {});
|
||||
}
|
||||
console.log(envMap);
|
||||
console.log('Environment map:', envMap);
|
||||
EOF
|
||||
fi
|
||||
|
||||
grep 'withPWA' ${NEXT_CONFIG_JS} >/dev/null && HAS_WITHPWA=true || HAS_WITHPWA=false
|
||||
# Add or update webpack configuration
|
||||
if ! grep -q '__xCfg__' "$NEXT_CONFIG_JS"; then
|
||||
cat << 'EOF' >> "$NEXT_CONFIG_JS"
|
||||
|
||||
if [ "$HAS_WITHPWA" == "true" ]; then
|
||||
if [ "$IMPORT_OR_REQUIRE" == "import" ]; then
|
||||
cat > ${NEXT_CONFIG_JS}.2 <<EOF
|
||||
const __xPWA__ = (p) => {
|
||||
const realPWA = withPWA(p);
|
||||
return (nextConfig) => {
|
||||
const modConfig = {...nextConfig};
|
||||
|
||||
modConfig.webpack = (config) => {
|
||||
const __xCfg__ = (nextConfig) => {
|
||||
return {
|
||||
...nextConfig,
|
||||
webpack: (config, options) => {
|
||||
config.plugins.push(new webpack.DefinePlugin(envMap));
|
||||
return nextConfig.webpack ? nextConfig.webpack(config) : config;
|
||||
};
|
||||
|
||||
return realPWA(modConfig);
|
||||
if (typeof nextConfig.webpack === 'function') {
|
||||
return nextConfig.webpack(config, options);
|
||||
}
|
||||
return config;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
EOF
|
||||
|
||||
# Update the export/module.exports line
|
||||
if [ "$IMPORT_OR_REQUIRE" = "import" ]; then
|
||||
sed -i 's/export default/const __orig_cfg__ =/' "$NEXT_CONFIG_JS"
|
||||
echo "export default __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS"
|
||||
else
|
||||
cat > ${NEXT_CONFIG_JS}.3 <<EOF
|
||||
const __xPWA__ = (nextConfig) => {
|
||||
const modConfig = {...nextConfig};
|
||||
|
||||
modConfig.webpack = (config) => {
|
||||
config.plugins.push(new webpack.DefinePlugin(envMap));
|
||||
return nextConfig.webpack ? nextConfig.webpack(config) : config;
|
||||
};
|
||||
|
||||
return withPWA(modConfig);
|
||||
};
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/withPWA(/__xPWA__(/g' > ${NEXT_CONFIG_JS}.4
|
||||
else
|
||||
cat > ${NEXT_CONFIG_JS}.3 <<EOF
|
||||
const __xCfg__ = (nextConfig) => {
|
||||
const modConfig = {...nextConfig};
|
||||
|
||||
modConfig.webpack = (config) => {
|
||||
config.plugins.push(new webpack.DefinePlugin(envMap));
|
||||
return nextConfig.webpack ? nextConfig.webpack(config) : config;
|
||||
};
|
||||
|
||||
return modConfig;
|
||||
};
|
||||
EOF
|
||||
if [ "$IMPORT_OR_REQUIRE" == "import" ]; then
|
||||
cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/export\s\+default\s\+/const __orig_cfg__ = /g' > ${NEXT_CONFIG_JS}.4
|
||||
echo "export default __xCfg__(__orig_cfg__);" > ${NEXT_CONFIG_JS}.5
|
||||
else
|
||||
cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/module.exports\s\+=\s\+/const __orig_cfg__ = /g' > ${NEXT_CONFIG_JS}.4
|
||||
echo "module.exports = __xCfg__(__orig_cfg__);" > ${NEXT_CONFIG_JS}.5
|
||||
sed -i 's/module.exports =/const __orig_cfg__ =/' "$NEXT_CONFIG_JS"
|
||||
echo "module.exports = __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean up the config file
|
||||
js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty"
|
||||
mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS"
|
||||
|
||||
rm -f ${NEXT_CONFIG_JS}
|
||||
for ((i=0; i <= 10; i++)); do
|
||||
if [ -s "${NEXT_CONFIG_JS}.${i}" ]; then
|
||||
if [ $i -le 2 ] ; then
|
||||
cat ${NEXT_CONFIG_JS}.${i} >> ${NEXT_CONFIG_JS}
|
||||
else
|
||||
cat ${NEXT_CONFIG_JS}.${i} | sed 's/^ *//g' | js-beautify | grep -v 'process\.\env\.' | js-beautify >> ${NEXT_CONFIG_JS}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
rm ${NEXT_CONFIG_JS}.*
|
||||
cat ${NEXT_CONFIG_JS} | js-beautify > ${NEXT_CONFIG_JS}.pretty
|
||||
mv ${NEXT_CONFIG_JS}.pretty ${NEXT_CONFIG_JS}
|
||||
|
||||
# Generate .env-list.json
|
||||
"${SCRIPT_DIR}/find-env.sh" "$(pwd)" > .env-list.json
|
||||
|
||||
if [ ! -f "package.dist" ]; then
|
||||
cp package.json package.dist
|
||||
fi
|
||||
# Update package.json
|
||||
[ ! -f "package.dist" ] && cp package.json package.dist
|
||||
|
||||
CUR_NEXT_VERSION="`jq -r '.dependencies.next' package.json`"
|
||||
|
||||
if [ "$CERC_NEXT_VERSION" != "keep" ] && [ "$CUR_NEXT_VERSION" != "$CERC_NEXT_VERSION" ]; then
|
||||
echo "Changing 'next' version specifier from '$CUR_NEXT_VERSION' to '$CERC_NEXT_VERSION' (set with '--extra-build-args \"--build-arg CERC_NEXT_VERSION=$CERC_NEXT_VERSION\"')"
|
||||
cat package.json | jq ".dependencies.next = \"$CERC_NEXT_VERSION\"" > package.json.$$
|
||||
mv package.json.$$ package.json
|
||||
fi
|
||||
|
||||
CUR_WEBPACK_VERSION="`jq -r '.dependencies.webpack' package.json`"
|
||||
if [ -z "$CUR_WEBPACK_VERSION" ]; then
|
||||
CUR_WEBPACK_VERSION="`jq -r '.devDependencies.webpack' package.json`"
|
||||
fi
|
||||
if [ "${CERC_WEBPACK_VERSION}" != "keep" ] || [ "${CUR_WEBPACK_VERSION}" == "null" ]; then
|
||||
if [ -z "$CERC_WEBPACK_VERSION" ] || [ "$CERC_WEBPACK_VERSION" == "keep" ]; then
|
||||
CERC_WEBPACK_VERSION="${CERC_DEFAULT_WEBPACK_VER}"
|
||||
fi
|
||||
echo "Webpack is required for env variable substitution. Adding to webpack@$CERC_WEBPACK_VERSION to dependencies..." 1>&2
|
||||
cat package.json | jq ".dependencies.webpack = \"$CERC_WEBPACK_VERSION\"" > package.json.$$
|
||||
mv package.json.$$ package.json
|
||||
fi
|
||||
|
||||
time $CERC_BUILD_TOOL install || exit 1
|
||||
|
||||
CUR_NEXT_VERSION=`jq -r '.version' node_modules/next/package.json`
|
||||
|
||||
# See https://github.com/vercel/next.js/discussions/46544
|
||||
semver -p -r ">=14.2.0" "$CUR_NEXT_VERSION"
|
||||
if [ $? -eq 0 ]; then
|
||||
# For >= 14.2.0
|
||||
CERC_NEXT_COMPILE_COMMAND="next build --experimental-build-mode compile"
|
||||
CERC_NEXT_GENERATE_COMMAND="next build --experimental-build-mode generate"
|
||||
# Check if webpack is already in package.json
|
||||
if WEBPACK_VERSION=$(jq -r '.dependencies.webpack // .devDependencies.webpack // empty' package.json); then
|
||||
if [ -n "$WEBPACK_VERSION" ]; then
|
||||
echo "Using existing webpack version: $WEBPACK_VERSION"
|
||||
else
|
||||
WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION")
|
||||
echo "Determined webpack version based on Next.js: $WEBPACK_VERSION"
|
||||
# Add webpack to devDependencies
|
||||
jq ".devDependencies.webpack = \"$WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json
|
||||
fi
|
||||
else
|
||||
# For 13.4.2 to 14.1.x
|
||||
CERC_NEXT_COMPILE_COMMAND="next experimental-compile"
|
||||
CERC_NEXT_GENERATE_COMMAND="next experimental-generate"
|
||||
WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION")
|
||||
echo "Determined webpack version based on Next.js: $WEBPACK_VERSION"
|
||||
# Add webpack to devDependencies
|
||||
jq ".devDependencies.webpack = \"$WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json
|
||||
fi
|
||||
|
||||
# Install dependencies
|
||||
$CERC_BUILD_TOOL install || exit 1
|
||||
|
||||
# Get the build command from package.json
|
||||
BUILD_COMMAND=`jq -r '.scripts.build // ""' package.json`
|
||||
|
||||
if [ -z "$BUILD_COMMAND" ]; then
|
||||
echo "No build command found in package.json. Using default 'next build'."
|
||||
BUILD_COMMAND="next build"
|
||||
fi
|
||||
|
||||
# Determine the appropriate build commands based on the Next.js version
|
||||
if semver -p -r ">=14.2.0" "$CERC_NEXT_VERSION"; then
|
||||
# For >= 14.2.0
|
||||
CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode compile}"
|
||||
CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode generate}"
|
||||
elif semver -p -r ">=13.4.2" "$CERC_NEXT_VERSION"; then
|
||||
# For 13.4.2 to 14.1.x
|
||||
CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next experimental-compile}"
|
||||
CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next experimental-generate}"
|
||||
else
|
||||
# For versions before 13.4.2
|
||||
CERC_NEXT_COMPILE_COMMAND="$BUILD_COMMAND"
|
||||
CERC_NEXT_GENERATE_COMMAND="$BUILD_COMMAND"
|
||||
fi
|
||||
|
||||
# Update package.json with the appropriate scripts
|
||||
cat package.json | jq ".scripts.cerc_compile = \"$CERC_NEXT_COMPILE_COMMAND\"" | jq ".scripts.cerc_generate = \"$CERC_NEXT_GENERATE_COMMAND\"" > package.json.$$
|
||||
mv package.json.$$ package.json
|
||||
|
||||
semver -p -r ">=$CERC_MIN_NEXTVER" $CUR_NEXT_VERSION
|
||||
if [ $? -ne 0 ]; then
|
||||
cat <<EOF
|
||||
|
||||
###############################################################################
|
||||
|
||||
WARNING: 'next' $CUR_NEXT_VERSION < minimum version $CERC_MIN_NEXTVER.
|
||||
|
||||
Attempting to build with '^$CERC_MIN_NEXTVER'. If this fails, you should upgrade
|
||||
the dependency in your webapp, or specify an explicit 'next' version
|
||||
to use for the build with:
|
||||
|
||||
--extra-build-args "--build-arg CERC_NEXT_VERSION=<version>"
|
||||
|
||||
###############################################################################
|
||||
|
||||
EOF
|
||||
cat package.json | jq ".dependencies.next = \"^$CERC_MIN_NEXTVER\"" > package.json.$$
|
||||
mv package.json.$$ package.json
|
||||
time $CERC_BUILD_TOOL install || exit 1
|
||||
fi
|
||||
|
||||
# Run the compile command
|
||||
time $CERC_BUILD_TOOL run cerc_compile || exit 1
|
||||
|
||||
exit 0
|
||||
exit 0
|
Loading…
Reference in New Issue
Block a user