# next.js (opens new window)

# build@10.0.2

  1. 初始
    1. 加载环境变量:使用@next/env根据运行模式,加载全局环境配置文件,使用dotenv解析
      • .env.${mode}.local
      • .env.local
      • .env.${mode}
      • .env
    2. 加载next.config.js配置
      • 支持function配置,(phase, {defaultConfig}) => config
      • 指定target必须是['server', 'serverless', 'experimental-serverless-trace']中的一项
      • 验证配置项数据类型、有效值、使用默认配置补全
      • 没有找到next.config.js,但找到不同后缀名的文件,提示格式不支持
    3. 确定buildId
    4. 加载自定义路由headers, rewrites, redirects(只影响服务端)
    5. 开启Spinner提示当前任务(后面不再列出)
    6. 开启Telemetry数据收集(后面不再列出) · 配置NEXT_TELEMETRY_DISABLED = true不运行
      • 基本信息
      • package.json中的dep以及version
    7. 验证TypeScript安装
      • 根据“tsconfig.json文件的存在”、“pages目录下有ts/tsx文件”确认项目使用了TypeScript
      • 确认typescript/@types/react/@types/node安装
      • 补全tsconfig.json内的配置
      • 创建next-env.d.ts文件
      • 运行type验证 · 配置typescript.ignoreBuildErrors=true不运行
  2. 编译
    1. 收集所有page路径pagePaths · 删除不用的页面,非页面脚本移到其他目录下
    2. 构建pageKeypagePath的映射对象mappedPages
    3. 根据mappedPages构建用于webpack配置entry,分为clientserver
      • client如:pages/user: next-client-pages-loader?page=xxx&absolutePagePath=xxx
      • server如:pages/user: [absolutePagePath_xxx]
    4. 页面路径确认
      • 确认没有和public下有冲突
      • _app|_document|_error只在pages根目录下有
    5. 输出routes-manifest.json
      • 由一些基本信息和headers, rewrites, redirects构成
    6. 构建webpack编译配置
      • client
      • server
    7. 运行webpack编译(此时编译结果已在.next目录下)
    8. 输出webpack编译errorswarnings
  3. 收集页面数据
    • 输出‘manifest’文件
    • 打印页面树结构

# next-client-pages-loader

# 默认的 splitChunks 配置

webpack4 开始使用 SplitChunksPlugin 拆分 chunks

{
    chunks: 'all',
    cacheGroups: {
        default: false,
        vendors: false,
        // In webpack 5 vendors was renamed to defaultVendors
        defaultVendors: false,
        framework: {
            chunks: 'all',
            name: 'framework',
            // This regex ignores nested copies of framework libraries so they're
            // bundled with their issuer.
            // https://github.com/vercel/next.js/pull/9012
            test: /(?<!node_modules.*)[\\/]node_modules[\\/](react|react-dom|scheduler|prop-types|use-subscription)[\\/]/,
            priority: 40,
            // Don't let webpack eliminate this chunk (prevents this chunk from
            // becoming a part of the commons chunk)
            enforce: true,
        },
        lib: {
            test(module: { size: Function; identifier: Function }): boolean {
                return (
                    module.size() > 160000 &&
                    /node_modules[/\\]/.test(module.identifier())
                )
            },
            name(module: {
                type: string
                libIdent?: Function
                updateHash: (hash: crypto.Hash) => void
            }): string {
                const hash = crypto.createHash('sha1')
                if (isModuleCSS(module)) {
                    module.updateHash(hash)
                } else {
                    if (!module.libIdent) {
                        throw new Error(
                        `Encountered unknown module type: ${module.type}. Please open an issue.`
                        )
                    }

                    hash.update(module.libIdent({ context: dir }))
                }

                return hash.digest('hex').substring(0, 8)
            },
            priority: 30,
            minChunks: 1,
            reuseExistingChunk: true,
        },
        commons: {
            name: 'commons',
            minChunks: totalPages,
            priority: 20,
        },
        shared: {
            name(module, chunks) {
                return (
                crypto
                    .createHash('sha1')
                    .update(
                    chunks.reduce(
                        (acc: string, chunk: webpack.compilation.Chunk) => {
                        return acc + chunk.name
                        },
                        ''
                    )
                    )
                    .digest('hex') + (isModuleCSS(module) ? '_CSS' : '')
                )
            },
            priority: 10,
            minChunks: 2,
            reuseExistingChunk: true,
        },
    },
    maxInitialRequests: 25,
    minSize: 20000,
}

# tsconfig.json

  1. 判断工程下是否有tsconfig.json文件
  2. 加载typescripttsconfig.json
  3. webpackConfig.resolve?.modules?.push(tsconfig.compilerOptions.baseUrl)
  4. webpackConfig.resolve?.plugins?.unshift(new JsConfigPathsPlugin(tsconfig.compilerOptions.paths, tsconfig.compilerOptions.baseUrl))
最后更新: 1/12/2023, 1:44:05 PM