UNPKG

@serwist/next

Version:

A module that integrates Serwist into your Next.js application.

1 lines 24.5 kB
{"version":3,"file":"index.mjs","names":["findFirstTruthy","arr","T","fn","elm","U","i","resolved","undefined","crypto","fs","getFileHash","file","PathOrFileDescriptor","createHash","update","readFileSync","digest","fs","getFileHash","getContentHash","file","PathOrFileDescriptor","isDev","slice","createRequire","require","import","meta","url","getPackageVersion","packageName","version","undefined","fs","path","TsConfigJson","TSConfigJSON","findFirstTruthy","loadTSConfig","baseDir","relativeTSConfigPath","tsConfigPath","filePath","resolvedPath","join","existsSync","undefined","JSON","parse","readFileSync","createRequire","bold","green","red","white","yellow","semver","require","import","meta","url","LOGGING_SPACE_PREFIX","gte","version","LoggingMethods","prefixedLog","prefixType","message","prefix","consoleMethod","Console","undefined","length","shift","console","wait","error","warn","info","event","SerwistConfigError","validationErrorMap","z","injectManifestOptions","InjectManifestOptionsComplete","validateInjectManifestOptions","input","result","safeParse","error","success","moduleName","message","prettifyError","data","fs","path","fileURLToPath","InjectManifest","ChildCompilationPlugin","relativeToOutputPath","globSync","NextConfig","Compilation","Configuration","default","Webpack","ExcludeParams","SerwistNextOptions","SerwistNextOptionsKey","getContentHash","getFileHash","loadTSConfig","logger","InjectManifestOptions","InjectManifestOptionsComplete","validateInjectManifestOptions","dirname","globalThis","__dirname","URL","import","meta","url","withSerwistInit","userOptions","nextConfig","process","env","SERWIST_SUPPRESS_TURBOPACK_WARNING","TURBOPACK","disable","console","warn","webpack","config","options","dev","basePath","tsConfigJson","dir","typescript","tsconfigPath","cacheOnNavigation","scope","swUrl","register","reloadOnOnline","globPublicPatterns","buildOptions","isServer","info","plugins","_sw","posix","join","_scope","push","DefinePlugin","Record","Exclude","swEntryJs","entry","Promise","entries","includes","Array","isArray","unshift","compilerOptions","types","swSrc","userSwSrc","swDest","userSwDest","additionalPrecacheEntries","exclude","manifestTransforms","otherBuildOptions","isAbsolute","publicDir","resolve","destDir","base","destBase","parse","cleanUpList","absolute","nodir","follow","cwd","file","rmSync","force","shouldBuildSWEntryWorker","swEntryPublicPath","swEntryWorkerDest","swEntryWorkerSrc","swEntryName","src","dest","Extract","event","resolvedManifestEntries","publicScan","ignore","map","f","revision","publicPath","output","disablePrecacheManifest","asset","compilation","swDestRelativeOutput","swAsset","getAsset","name","startsWith","test","manifestEntries","publicDirRelativeOutput","publicFilesPrefix","manifest","m","replace","warnings","PluginOptions","PluginOptionsComplete"],"sources":["../src/lib/find-first-truthy.ts","../src/lib/get-file-hash.ts","../src/lib/get-content-hash.ts","../src/lib/get-package-version.ts","../src/lib/load-tsconfig.ts","../src/lib/logger.ts","../src/lib/validator.ts","../src/index.ts"],"sourcesContent":["/**\n * Find the first truthy value in an array.\n * @param arr\n * @param fn\n * @returns\n */\nexport const findFirstTruthy = <T, U>(arr: T[], fn: (elm: T) => U) => {\n for (const i of arr) {\n const resolved = fn(i);\n if (resolved) {\n return resolved;\n }\n }\n return undefined;\n};\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\n\nexport const getFileHash = (file: fs.PathOrFileDescriptor) => crypto.createHash(\"md5\").update(fs.readFileSync(file)).digest(\"hex\");\n","import type fs from \"node:fs\";\n\nimport { getFileHash } from \"./get-file-hash.js\";\n\nexport const getContentHash = (file: fs.PathOrFileDescriptor, isDev: boolean) => {\n if (isDev) {\n return \"development\";\n }\n return getFileHash(file).slice(0, 16);\n};\n","import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get a package's version\n * @param packageName\n * @returns\n */\nexport const getPackageVersion = (packageName: string): string | undefined => {\n try {\n return require(`${packageName}/package.json`).version;\n } catch {\n return undefined;\n }\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { TsConfigJson as TSConfigJSON } from \"type-fest\";\n\nimport { findFirstTruthy } from \"./find-first-truthy.js\";\n\nexport const loadTSConfig = (baseDir: string, relativeTSConfigPath: string | undefined): TSConfigJSON | undefined => {\n try {\n // Find tsconfig.json file\n const tsConfigPath = findFirstTruthy([relativeTSConfigPath ?? \"tsconfig.json\", \"jsconfig.json\"], (filePath) => {\n const resolvedPath = path.join(baseDir, filePath);\n return fs.existsSync(resolvedPath) ? resolvedPath : undefined;\n });\n if (!tsConfigPath) {\n return undefined;\n }\n // Read tsconfig.json file\n return JSON.parse(fs.readFileSync(tsConfigPath, \"utf-8\"));\n } catch {\n return undefined;\n }\n};\n","import { createRequire } from \"node:module\";\nimport { bold, green, red, white, yellow } from \"kolorist\";\nimport semver from \"semver\";\n\nconst require = createRequire(import.meta.url);\n\nconst LOGGING_SPACE_PREFIX = semver.gte(require(\"next/package.json\").version, \"16.0.0\") ? \"\" : \" \";\n\nexport type LoggingMethods = \"wait\" | \"error\" | \"warn\" | \"info\" | \"event\";\n\nconst prefixedLog = (prefixType: LoggingMethods, ...message: any[]) => {\n let prefix: string;\n let consoleMethod: keyof Console;\n\n switch (prefixType) {\n case \"wait\":\n prefix = `${white(bold(\"\"))} (serwist)`;\n consoleMethod = \"log\";\n break;\n case \"error\":\n prefix = `${red(bold(\"X\"))} (serwist)`;\n consoleMethod = \"error\";\n break;\n case \"warn\":\n prefix = `${yellow(bold(\"\"))} (serwist)`;\n consoleMethod = \"warn\";\n break;\n case \"info\":\n prefix = `${white(bold(\"\"))} (serwist)`;\n consoleMethod = \"log\";\n break;\n case \"event\":\n prefix = `${green(bold(\"\"))} (serwist)`;\n consoleMethod = \"log\";\n break;\n }\n\n if ((message[0] === \"\" || message[0] === undefined) && message.length === 1) {\n message.shift();\n }\n\n // If there's no message, don't print the prefix but a new line\n if (message.length === 0) {\n console[consoleMethod](\"\");\n } else {\n console[consoleMethod](`${LOGGING_SPACE_PREFIX}${prefix}`, ...message);\n }\n};\n\nexport const wait = (...message: any[]) => prefixedLog(\"wait\", ...message);\n\nexport const error = (...message: any[]) => prefixedLog(\"error\", ...message);\n\nexport const warn = (...message: any[]) => prefixedLog(\"warn\", ...message);\n\nexport const info = (...message: any[]) => prefixedLog(\"info\", ...message);\n\nexport const event = (...message: any[]) => prefixedLog(\"event\", ...message);\n","import { SerwistConfigError, validationErrorMap } from \"@serwist/build/schema\";\nimport { z } from \"zod\";\nimport { injectManifestOptions } from \"./schema.js\";\nimport type { InjectManifestOptionsComplete } from \"./types.js\";\n\nexport const validateInjectManifestOptions = (input: unknown): InjectManifestOptionsComplete => {\n const result = injectManifestOptions.safeParse(input, {\n error: validationErrorMap,\n });\n if (!result.success) {\n throw new SerwistConfigError({ moduleName: \"@serwist/next\", message: z.prettifyError(result.error) });\n }\n return result.data;\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { InjectManifest } from \"@serwist/webpack-plugin\";\nimport { ChildCompilationPlugin, relativeToOutputPath } from \"@serwist/webpack-plugin/internal\";\nimport { globSync } from \"glob\";\nimport type { NextConfig } from \"next\";\nimport type { Compilation, Configuration, default as Webpack } from \"webpack\";\nimport type { ExcludeParams, SerwistNextOptions, SerwistNextOptionsKey } from \"./internal-types.js\";\nimport { getContentHash, getFileHash, loadTSConfig, logger } from \"./lib/index.js\";\nimport type { InjectManifestOptions, InjectManifestOptionsComplete } from \"./lib/types.js\";\nimport { validateInjectManifestOptions } from \"./lib/validator.js\";\n\nconst dirname = \"__dirname\" in globalThis ? __dirname : fileURLToPath(new URL(\".\", import.meta.url));\n\n/**\n * Integrates Serwist into your Next.js app.\n * @param userOptions\n * @returns\n */\nconst withSerwistInit = (userOptions: InjectManifestOptions): ((nextConfig?: NextConfig) => NextConfig) => {\n if (!process.env.SERWIST_SUPPRESS_TURBOPACK_WARNING && process.env.TURBOPACK && !userOptions.disable) {\n process.env.SERWIST_SUPPRESS_TURBOPACK_WARNING = \"1\";\n console.warn(\n `[@serwist/next] WARNING: You are using '@serwist/next' with \\`next dev --turbopack\\`, but it doesn't support Turbopack. Do one of the following:\n\n- Set \\`disable\\` to \\`process.env.NODE_ENV !== \"production\"\\`.\n\n- Use webpack by running \\`next dev --webpack\\` instead of \\`next dev --turbopack\\`.\n\n- Migrate to '@serwist/turbopack' which has experimental support for Turbopack. See https://serwist.pages.dev/docs/next/turbo for more information.\n\n- Migrate to configurator mode which has support for Turbopack. See https://serwist.pages.dev/docs/next/config for more information. \n\nFollow https://github.com/serwist/serwist/issues/54 for progress on Serwist + Turbopack. You can also suppress this warning by setting SERWIST_SUPPRESS_TURBOPACK_WARNING=1.\\n`,\n );\n }\n return (nextConfig = {}) => ({\n ...nextConfig,\n webpack(config: Configuration, options) {\n const webpack: typeof Webpack = options.webpack;\n const { dev } = options;\n\n const basePath = options.config.basePath || \"/\";\n\n const tsConfigJson = loadTSConfig(options.dir, nextConfig?.typescript?.tsconfigPath);\n\n const {\n cacheOnNavigation,\n disable,\n scope = basePath,\n swUrl,\n register,\n reloadOnOnline,\n globPublicPatterns,\n ...buildOptions\n } = validateInjectManifestOptions(userOptions);\n\n if (typeof nextConfig.webpack === \"function\") {\n config = nextConfig.webpack(config, options);\n }\n\n if (disable) {\n options.isServer && logger.info(\"Serwist is disabled.\");\n return config;\n }\n\n if (!config.plugins) {\n config.plugins = [];\n }\n\n const _sw = path.posix.join(basePath, swUrl);\n const _scope = path.posix.join(scope, \"/\");\n\n config.plugins.push(\n new webpack.DefinePlugin({\n \"self.__SERWIST_SW_ENTRY.sw\": `'${_sw}'`,\n \"self.__SERWIST_SW_ENTRY.scope\": `'${_scope}'`,\n \"self.__SERWIST_SW_ENTRY.cacheOnNavigation\": `${cacheOnNavigation}`,\n \"self.__SERWIST_SW_ENTRY.register\": `${register}`,\n \"self.__SERWIST_SW_ENTRY.reloadOnOnline\": `${reloadOnOnline}`,\n } satisfies Record<`${SerwistNextOptionsKey}.${Exclude<keyof SerwistNextOptions, \"swEntryWorker\">}`, string | undefined>),\n );\n\n const swEntryJs = path.join(dirname, \"sw-entry.mjs\");\n const entry = config.entry as () => Promise<Record<string, string[] | string>>;\n config.entry = async () => {\n const entries = await entry();\n if (entries[\"main.js\"] && !entries[\"main.js\"].includes(swEntryJs)) {\n if (Array.isArray(entries[\"main.js\"])) {\n entries[\"main.js\"].unshift(swEntryJs);\n } else if (typeof entries[\"main.js\"] === \"string\") {\n entries[\"main.js\"] = [swEntryJs, entries[\"main.js\"]];\n }\n }\n if (entries[\"main-app\"] && !entries[\"main-app\"].includes(swEntryJs)) {\n if (Array.isArray(entries[\"main-app\"])) {\n entries[\"main-app\"].unshift(swEntryJs);\n } else if (typeof entries[\"main-app\"] === \"string\") {\n entries[\"main-app\"] = [swEntryJs, entries[\"main-app\"]];\n }\n }\n return entries;\n };\n\n if (!options.isServer) {\n if (!register) {\n logger.info(\n \"The service worker will not be automatically registered, please call 'window.serwist.register()' in 'componentDidMount' or 'useEffect'.\",\n );\n\n if (!tsConfigJson?.compilerOptions?.types?.includes(\"@serwist/next/typings\")) {\n logger.info(\n \"You may also want to add '@serwist/next/typings' to your TypeScript/JavaScript configuration file at 'compilerOptions.types'.\",\n );\n }\n }\n\n const {\n swSrc: userSwSrc,\n swDest: userSwDest,\n additionalPrecacheEntries,\n exclude,\n manifestTransforms = [],\n ...otherBuildOptions\n } = buildOptions;\n\n let swSrc = userSwSrc;\n let swDest = userSwDest;\n\n // If these two paths are not absolute, they will be resolved from `compilation.options.output.path`,\n // which is `${options.dir}/${nextConfig.destDir}` for Next.js apps, rather than `${options.dir}`\n // as an user would expect.\n if (!path.isAbsolute(swSrc)) {\n swSrc = path.join(options.dir, swSrc);\n }\n if (!path.isAbsolute(swDest)) {\n swDest = path.join(options.dir, swDest);\n }\n\n const publicDir = path.resolve(options.dir, \"public\");\n const { dir: destDir, base: destBase } = path.parse(swDest);\n\n const cleanUpList = globSync([\"swe-worker-*.js\", \"swe-worker-*.js.map\", destBase, `${destBase}.map`], {\n absolute: true,\n nodir: true,\n follow: true,\n cwd: destDir,\n });\n\n for (const file of cleanUpList) {\n fs.rmSync(file, { force: true });\n }\n\n const shouldBuildSWEntryWorker = cacheOnNavigation;\n let swEntryPublicPath: string | undefined;\n let swEntryWorkerDest: string | undefined;\n\n if (shouldBuildSWEntryWorker) {\n const swEntryWorkerSrc = path.join(dirname, \"sw-entry-worker.mjs\");\n const swEntryName = `swe-worker-${getContentHash(swEntryWorkerSrc, dev)}.js`;\n swEntryPublicPath = path.posix.join(basePath, swEntryName);\n swEntryWorkerDest = path.join(destDir, swEntryName);\n config.plugins.push(\n new ChildCompilationPlugin({\n src: swEntryWorkerSrc,\n dest: swEntryWorkerDest,\n }),\n );\n }\n config.plugins.push(\n new webpack.DefinePlugin({\n \"self.__SERWIST_SW_ENTRY.swEntryWorker\": swEntryPublicPath && `'${swEntryPublicPath}'`,\n } satisfies Record<`${SerwistNextOptionsKey}.${Extract<keyof SerwistNextOptions, \"swEntryWorker\">}`, string | undefined>),\n );\n\n logger.event(`Bundling the service worker script with the URL '${_sw}' and the scope '${_scope}'...`);\n\n // Precache files in public folder\n let resolvedManifestEntries = additionalPrecacheEntries;\n\n if (!resolvedManifestEntries) {\n const publicScan = globSync(globPublicPatterns, {\n nodir: true,\n follow: true,\n cwd: publicDir,\n ignore: [\"swe-worker-*.js\", destBase, `${destBase}.map`],\n });\n resolvedManifestEntries = publicScan.map((f) => ({\n url: path.posix.join(basePath, f),\n revision: getFileHash(path.join(publicDir, f)),\n }));\n }\n\n const publicPath = config.output?.publicPath;\n\n config.plugins.push(\n new InjectManifest({\n swSrc,\n swDest,\n disablePrecacheManifest: dev,\n additionalPrecacheEntries: dev ? [] : resolvedManifestEntries,\n exclude: [\n ...exclude,\n ({ asset, compilation }: ExcludeParams) => {\n // Same as how `@serwist/webpack-plugin` does it. It is always\n // `relativeToOutputPath(compilation, originalSwDest)`.\n const swDestRelativeOutput = relativeToOutputPath(compilation, swDest);\n const swAsset = compilation.getAsset(swDestRelativeOutput);\n return (\n // We don't need the service worker to be cached.\n asset.name === swAsset?.name ||\n asset.name.startsWith(\"server/\") ||\n // This excludes all JSON files in the compilation directory by filtering\n // out paths that have slashes or don't end with `.json`. Only said files\n // match this criterion.\n /^[^/]*\\.json$/.test(asset.name) ||\n (dev && !asset.name.startsWith(\"static/runtime/\"))\n );\n },\n ],\n manifestTransforms: [\n ...manifestTransforms,\n async (manifestEntries, compilation) => {\n // This path always uses forward slashes, so it is safe to use it in the following string replace.\n const publicDirRelativeOutput = relativeToOutputPath(compilation as Compilation, publicDir);\n // `publicPath` is always `${assetPrefix}/_next/` for Next.js apps.\n const publicFilesPrefix = `${publicPath}${publicDirRelativeOutput}`;\n const manifest = manifestEntries.map((m) => {\n m.url = m.url.replace(\"/_next//static/image\", \"/_next/static/image\").replace(\"/_next//static/media\", \"/_next/static/media\");\n // We remove `${publicPath}/${publicDirRelativeOutput}` because `assetPrefix`\n // is not intended for files that are in the public directory and we also want\n // to remove `/_next/${publicDirRelativeOutput}` from the URL, since that is not how\n // we resolve files in the public directory.\n if (m.url.startsWith(publicFilesPrefix)) {\n m.url = path.posix.join(basePath, m.url.replace(publicFilesPrefix, \"\"));\n }\n m.url = m.url.replace(/\\[/g, \"%5B\").replace(/\\]/g, \"%5D\").replace(/@/g, \"%40\");\n return m;\n });\n return { manifest, warnings: [] };\n },\n ],\n ...otherBuildOptions,\n }),\n );\n }\n\n return config;\n },\n });\n};\n\nexport default withSerwistInit;\nexport { validateInjectManifestOptions };\nexport type { InjectManifestOptions as PluginOptions, InjectManifestOptionsComplete as PluginOptionsComplete };\n"],"mappings":"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"}