index.js 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  21. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  22. mod
  23. ));
  24. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  25. // src/index.ts
  26. var src_exports = {};
  27. __export(src_exports, {
  28. VitePWA: () => VitePWA,
  29. cachePreset: () => cachePreset,
  30. defaultInjectManifestVitePlugins: () => defaultInjectManifestVitePlugins
  31. });
  32. module.exports = __toCommonJS(src_exports);
  33. // src/context.ts
  34. function createContext(userOptions) {
  35. return {
  36. userOptions,
  37. options: void 0,
  38. viteConfig: void 0,
  39. useImportRegister: false,
  40. devEnvironment: false
  41. };
  42. }
  43. // src/constants.ts
  44. var FILE_SW_REGISTER = "registerSW.js";
  45. var VIRTUAL_MODULES_MAP = {
  46. "virtual:pwa-register": "register",
  47. "virtual:pwa-register/vue": "vue",
  48. "virtual:pwa-register/svelte": "svelte",
  49. "virtual:pwa-register/react": "react",
  50. "virtual:pwa-register/preact": "preact",
  51. "virtual:pwa-register/solid": "solid"
  52. };
  53. var VIRTUAL_MODULES_RESOLVE_PREFIX = "/@vite-plugin-pwa/";
  54. var VIRTUAL_MODULES = Object.keys(VIRTUAL_MODULES_MAP);
  55. var defaultInjectManifestVitePlugins = [
  56. "alias",
  57. "commonjs",
  58. "vite:resolve",
  59. "vite:esbuild",
  60. "replace",
  61. "vite:define",
  62. "rollup-plugin-dynamic-import-variables",
  63. "vite:esbuild-transpile",
  64. "vite:json",
  65. "vite:terser"
  66. ];
  67. var PWA_INFO_VIRTUAL = "virtual:pwa-info";
  68. var RESOLVED_PWA_INFO_VIRTUAL = `\0${PWA_INFO_VIRTUAL}`;
  69. var DEV_SW_NAME = "dev-sw.js?dev-sw";
  70. var DEV_SW_VIRTUAL = `${VIRTUAL_MODULES_RESOLVE_PREFIX}pwa-entry-point-loaded`;
  71. var RESOLVED_DEV_SW_VIRTUAL = `\0${DEV_SW_VIRTUAL}`;
  72. var DEV_READY_NAME = "vite-pwa-plugin:dev-ready";
  73. var DEV_REGISTER_SW_NAME = "vite-plugin-pwa:register-sw";
  74. // src/html.ts
  75. function generateSimpleSWRegister(options2, dev) {
  76. const path = dev ? `${options2.base}${DEV_SW_NAME}` : `${options2.base}${options2.filename}`;
  77. if (dev) {
  78. const swType = options2.devOptions.type ?? "classic";
  79. return `if('serviceWorker' in navigator) navigator.serviceWorker.register('${path}', { scope: '${options2.scope}', type: '${swType}' })`;
  80. }
  81. return `
  82. if('serviceWorker' in navigator) {
  83. window.addEventListener('load', () => {
  84. navigator.serviceWorker.register('${path}', { scope: '${options2.scope}' })
  85. })
  86. }`.replace(/\n/g, "");
  87. }
  88. function injectServiceWorker(html, options2, dev) {
  89. const manifest = generateWebManifest(options2, dev);
  90. if (!dev) {
  91. const script = generateRegisterSW(options2, dev);
  92. if (script) {
  93. return html.replace(
  94. "</head>",
  95. `${manifest}${script}</head>`
  96. );
  97. }
  98. }
  99. return html.replace(
  100. "</head>",
  101. `${manifest}</head>`
  102. );
  103. }
  104. function generateWebManifest(options2, dev) {
  105. const crossorigin = options2.useCredentials ? ' crossorigin="use-credentials"' : "";
  106. if (dev) {
  107. const name = options2.devOptions.webManifestUrl ?? `${options2.base}${options2.manifestFilename}`;
  108. return options2.manifest ? `<link rel="manifest" href="${name}"${crossorigin}>` : "";
  109. } else {
  110. return options2.manifest ? `<link rel="manifest" href="${options2.base}${options2.manifestFilename}"${crossorigin}>` : "";
  111. }
  112. }
  113. function generateRegisterSW(options2, dev) {
  114. if (options2.injectRegister === "inline")
  115. return `<script id="vite-plugin-pwa:inline-sw">${generateSimpleSWRegister(options2, dev)}<\/script>`;
  116. else if (options2.injectRegister === "script")
  117. return `<script id="vite-plugin-pwa:register-sw" src="${options2.base}${FILE_SW_REGISTER}"><\/script>`;
  118. return void 0;
  119. }
  120. function generateRegisterDevSW() {
  121. return `<script id="vite-plugin-pwa:register-dev-sw" type="module">
  122. import registerDevSW from '${DEV_SW_VIRTUAL}';
  123. registerDevSW();
  124. <\/script>`;
  125. }
  126. function generateSWHMR() {
  127. return `
  128. import.meta.hot.on('${DEV_REGISTER_SW_NAME}', ({ inline, inlinePath, registerPath, scope, swType = 'classic' }) => {
  129. if (inline) {
  130. if('serviceWorker' in navigator) {
  131. navigator.serviceWorker.register(inlinePath, { scope, type: swType });
  132. }
  133. }
  134. else {
  135. const registerSW = document.createElement('script');
  136. registerSW.setAttribute('id', 'vite-plugin-pwa:register-sw');
  137. registerSW.setAttribute('src', registerPath);
  138. document.head.appendChild(registerSW);
  139. }
  140. });
  141. function registerDevSW() {
  142. try {
  143. import.meta.hot.send('${DEV_READY_NAME}');
  144. } catch (e) {
  145. console.error('unable to send ${DEV_READY_NAME} message to register service worker in dev mode!', e);
  146. }
  147. }
  148. export default registerDevSW;
  149. `;
  150. }
  151. // src/api.ts
  152. var import_path4 = require("path");
  153. var import_fs3 = require("fs");
  154. // src/modules.ts
  155. var import_path2 = require("path");
  156. var import_fs = require("fs");
  157. var import_url = require("url");
  158. // src/log.ts
  159. var import_path = require("path");
  160. // node_modules/.pnpm/kolorist@1.6.0/node_modules/kolorist/dist/esm/index.mjs
  161. var enabled = true;
  162. var globalVar = typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {};
  163. var supportLevel = 0;
  164. if (globalVar.process && globalVar.process.env && globalVar.process.stdout) {
  165. const { FORCE_COLOR, NODE_DISABLE_COLORS, TERM } = globalVar.process.env;
  166. if (NODE_DISABLE_COLORS || FORCE_COLOR === "0") {
  167. enabled = false;
  168. } else if (FORCE_COLOR === "1") {
  169. enabled = true;
  170. } else if (TERM === "dumb") {
  171. enabled = false;
  172. } else if ("CI" in globalVar.process.env && [
  173. "TRAVIS",
  174. "CIRCLECI",
  175. "APPVEYOR",
  176. "GITLAB_CI",
  177. "GITHUB_ACTIONS",
  178. "BUILDKITE",
  179. "DRONE"
  180. ].some((vendor) => vendor in globalVar.process.env)) {
  181. enabled = true;
  182. } else {
  183. enabled = process.stdout.isTTY;
  184. }
  185. if (enabled) {
  186. supportLevel = TERM && TERM.endsWith("-256color") ? 2 : 1;
  187. }
  188. }
  189. var options = {
  190. enabled,
  191. supportLevel
  192. };
  193. function kolorist(start, end, level = 1) {
  194. const open = `\x1B[${start}m`;
  195. const close = `\x1B[${end}m`;
  196. const regex = new RegExp(`\\x1b\\[${end}m`, "g");
  197. return (str) => {
  198. return options.enabled && options.supportLevel >= level ? open + ("" + str).replace(regex, open) + close : "" + str;
  199. };
  200. }
  201. var reset = kolorist(0, 0);
  202. var bold = kolorist(1, 22);
  203. var dim = kolorist(2, 22);
  204. var italic = kolorist(3, 23);
  205. var underline = kolorist(4, 24);
  206. var inverse = kolorist(7, 27);
  207. var hidden = kolorist(8, 28);
  208. var strikethrough = kolorist(9, 29);
  209. var black = kolorist(30, 39);
  210. var red = kolorist(31, 39);
  211. var green = kolorist(32, 39);
  212. var yellow = kolorist(33, 39);
  213. var blue = kolorist(34, 39);
  214. var magenta = kolorist(35, 39);
  215. var cyan = kolorist(36, 39);
  216. var white = kolorist(97, 39);
  217. var gray = kolorist(90, 39);
  218. var lightGray = kolorist(37, 39);
  219. var lightRed = kolorist(91, 39);
  220. var lightGreen = kolorist(92, 39);
  221. var lightYellow = kolorist(93, 39);
  222. var lightBlue = kolorist(94, 39);
  223. var lightMagenta = kolorist(95, 39);
  224. var lightCyan = kolorist(96, 39);
  225. var bgBlack = kolorist(40, 49);
  226. var bgRed = kolorist(41, 49);
  227. var bgGreen = kolorist(42, 49);
  228. var bgYellow = kolorist(43, 49);
  229. var bgBlue = kolorist(44, 49);
  230. var bgMagenta = kolorist(45, 49);
  231. var bgCyan = kolorist(46, 49);
  232. var bgWhite = kolorist(107, 49);
  233. var bgGray = kolorist(100, 49);
  234. var bgLightRed = kolorist(101, 49);
  235. var bgLightGreen = kolorist(102, 49);
  236. var bgLightYellow = kolorist(103, 49);
  237. var bgLightBlue = kolorist(104, 49);
  238. var bgLightMagenta = kolorist(105, 49);
  239. var bgLightCyan = kolorist(106, 49);
  240. var bgLightGray = kolorist(47, 49);
  241. // package.json
  242. var version = "0.14.0";
  243. // src/log.ts
  244. function logWorkboxResult(strategy, buildResult, viteOptions) {
  245. const { root, logLevel = "info" } = viteOptions;
  246. if (logLevel === "silent")
  247. return;
  248. const { count, size, filePaths, warnings } = buildResult;
  249. if (logLevel === "info") {
  250. console.info([
  251. "",
  252. `${cyan(`PWA v${version}`)}`,
  253. `mode ${magenta(strategy)}`,
  254. `precache ${green(`${count} entries`)} ${dim(`(${(size / 1024).toFixed(2)} KiB)`)}`,
  255. "files generated",
  256. ...filePaths.map((p) => ` ${dim((0, import_path.relative)(root, p))}`)
  257. ].join("\n"));
  258. }
  259. warnings && warnings.length > 0 && console.warn(yellow([
  260. "warnings",
  261. ...warnings.map((w) => ` ${w}`),
  262. ""
  263. ].join("\n")));
  264. }
  265. // src/modules.ts
  266. var import_meta = {};
  267. var _dirname = typeof __dirname !== "undefined" ? __dirname : (0, import_path2.dirname)((0, import_url.fileURLToPath)(import_meta.url));
  268. async function loadWorkboxBuild() {
  269. try {
  270. const workbox = await import("workbox-build");
  271. return workbox.default ?? workbox;
  272. } catch (_) {
  273. return require("workbox-build");
  274. }
  275. }
  276. async function loadRollupReplacePlugin() {
  277. try {
  278. const { createRequire } = await import("module").then((m) => m.default || m);
  279. const nodeRequire = createRequire(_dirname);
  280. return nodeRequire("@rollup/plugin-replace");
  281. } catch (_) {
  282. return require("@rollup/plugin-replace");
  283. }
  284. }
  285. async function generateRegisterSW2(options2, mode, source = "register") {
  286. const sw = options2.base + options2.filename;
  287. const scope = options2.scope;
  288. const content = await import_fs.promises.readFile((0, import_path2.resolve)(_dirname, `client/${mode}/${source}.mjs`), "utf-8");
  289. return content.replace(/__SW__/g, sw).replace("__SCOPE__", scope).replace("__SW_AUTO_UPDATE__", `${options2.registerType === "autoUpdate"}`).replace("__SW_SELF_DESTROYING__", `${options2.selfDestroying}`).replace("__TYPE__", `${options2.devOptions.enabled ? options2.devOptions.type : "classic"}`);
  290. }
  291. async function generateServiceWorker(options2, viteOptions) {
  292. if (options2.selfDestroying) {
  293. const selfDestroyingSW = `
  294. self.addEventListener('install', function(e) {
  295. self.skipWaiting();
  296. });
  297. self.addEventListener('activate', function(e) {
  298. self.registration.unregister()
  299. .then(function() {
  300. return self.clients.matchAll();
  301. })
  302. .then(function(clients) {
  303. clients.forEach(client => client.navigate(client.url))
  304. });
  305. });
  306. `;
  307. await import_fs.promises.writeFile(options2.swDest.replace(/\\/g, "/"), selfDestroyingSW, { encoding: "utf8" });
  308. return {
  309. count: 1,
  310. size: selfDestroyingSW.length,
  311. warnings: [],
  312. filePaths: [options2.filename]
  313. };
  314. }
  315. const { generateSW } = await loadWorkboxBuild();
  316. const buildResult = await generateSW(options2.workbox);
  317. logWorkboxResult("generateSW", buildResult, viteOptions);
  318. return buildResult;
  319. }
  320. async function generateInjectManifest(options2, viteOptions) {
  321. const { selfDestroying } = options2;
  322. if (selfDestroying) {
  323. await generateServiceWorker(options2, viteOptions);
  324. return;
  325. }
  326. const vitePlugins = options2.vitePlugins;
  327. const includedPluginNames = [];
  328. if (typeof vitePlugins === "function")
  329. includedPluginNames.push(...vitePlugins(viteOptions.plugins.map((p) => p.name)));
  330. else
  331. includedPluginNames.push(...vitePlugins);
  332. if (includedPluginNames.length === 0)
  333. includedPluginNames.push(...defaultInjectManifestVitePlugins);
  334. const replace = await loadRollupReplacePlugin();
  335. const plugins = [
  336. replace({
  337. "preventAssignment": true,
  338. "process.env.NODE_ENV": JSON.stringify(options2.mode)
  339. }),
  340. ...viteOptions.plugins.filter((p) => includedPluginNames.includes(p.name))
  341. ];
  342. const { rollup } = await import("rollup");
  343. const bundle = await rollup({
  344. input: options2.swSrc,
  345. plugins
  346. });
  347. try {
  348. await bundle.write({
  349. format: options2.rollupFormat,
  350. exports: "none",
  351. inlineDynamicImports: true,
  352. file: options2.injectManifest.swDest,
  353. sourcemap: viteOptions.build.sourcemap
  354. });
  355. } finally {
  356. await bundle.close();
  357. }
  358. if (!options2.injectManifest.injectionPoint)
  359. return;
  360. const injectManifestOptions = {
  361. ...options2.injectManifest,
  362. swSrc: options2.injectManifest.swDest
  363. };
  364. const { injectManifest } = await loadWorkboxBuild();
  365. const buildResult = await injectManifest(injectManifestOptions);
  366. logWorkboxResult("injectManifest", buildResult, viteOptions);
  367. }
  368. // src/assets.ts
  369. var import_path3 = require("path");
  370. var import_fs2 = __toESM(require("fs"));
  371. var import_crypto = __toESM(require("crypto"));
  372. var import_fast_glob = __toESM(require("fast-glob"));
  373. function buildManifestEntry(publicDir, url) {
  374. return new Promise((resolve5, reject) => {
  375. const cHash = import_crypto.default.createHash("MD5");
  376. const stream = import_fs2.default.createReadStream((0, import_path3.resolve)(publicDir, url));
  377. stream.on("error", (err) => {
  378. reject(err);
  379. });
  380. stream.on("data", (chunk) => {
  381. cHash.update(chunk);
  382. });
  383. stream.on("end", () => {
  384. return resolve5({
  385. url,
  386. revision: `${cHash.digest("hex")}`
  387. });
  388. });
  389. });
  390. }
  391. function lookupAdditionalManifestEntries(useInjectManifest, injectManifest, workbox) {
  392. return useInjectManifest ? injectManifest.additionalManifestEntries || [] : workbox.additionalManifestEntries || [];
  393. }
  394. function normalizeIconPath(path) {
  395. return path.startsWith("/") ? path.substring(1) : path;
  396. }
  397. function includeIcons(icons, globs) {
  398. Object.keys(icons).forEach((key) => {
  399. const icon = icons[key];
  400. const src = normalizeIconPath(icon.src);
  401. if (!globs.includes(src))
  402. globs.push(src);
  403. });
  404. }
  405. async function configureStaticAssets(resolvedVitePWAOptions, viteConfig) {
  406. const {
  407. manifest,
  408. strategies,
  409. injectManifest,
  410. workbox,
  411. includeAssets,
  412. includeManifestIcons,
  413. manifestFilename
  414. } = resolvedVitePWAOptions;
  415. const useInjectManifest = strategies === "injectManifest";
  416. const { publicDir } = viteConfig;
  417. const globs = [];
  418. const manifestEntries = lookupAdditionalManifestEntries(
  419. useInjectManifest,
  420. injectManifest,
  421. workbox
  422. );
  423. if (includeAssets) {
  424. if (Array.isArray(includeAssets))
  425. globs.push(...includeAssets.map(normalizeIconPath));
  426. else
  427. globs.push(normalizeIconPath(includeAssets));
  428. }
  429. if (includeManifestIcons && manifest) {
  430. manifest.icons && includeIcons(manifest.icons, globs);
  431. manifest.shortcuts && manifest.shortcuts.forEach((s) => {
  432. s.icons && includeIcons(s.icons, globs);
  433. });
  434. }
  435. if (globs.length > 0) {
  436. let assets = await (0, import_fast_glob.default)(
  437. globs,
  438. {
  439. cwd: publicDir,
  440. onlyFiles: true,
  441. unique: true
  442. }
  443. );
  444. if (manifestEntries.length > 0) {
  445. const included = manifestEntries.map((me) => {
  446. if (typeof me === "string")
  447. return me;
  448. else
  449. return me.url;
  450. });
  451. assets = assets.filter((a) => !included.includes(a));
  452. }
  453. const assetsEntries = await Promise.all(assets.map((a) => {
  454. return buildManifestEntry(publicDir, a);
  455. }));
  456. manifestEntries.push(...assetsEntries);
  457. }
  458. if (manifest) {
  459. const cHash = import_crypto.default.createHash("MD5");
  460. cHash.update(generateWebManifestFile(resolvedVitePWAOptions));
  461. manifestEntries.push({
  462. url: manifestFilename,
  463. revision: `${cHash.digest("hex")}`
  464. });
  465. }
  466. if (manifestEntries.length > 0) {
  467. if (useInjectManifest)
  468. injectManifest.additionalManifestEntries = manifestEntries;
  469. else
  470. workbox.additionalManifestEntries = manifestEntries;
  471. }
  472. }
  473. function generateWebManifestFile(options2) {
  474. return `${JSON.stringify(options2.manifest, null, options2.minify ? 0 : 2)}
  475. `;
  476. }
  477. // src/api.ts
  478. async function _generateSW({ options: options2, viteConfig }) {
  479. if (options2.disable)
  480. return;
  481. if (options2.strategies === "injectManifest")
  482. await generateInjectManifest(options2, viteConfig);
  483. else
  484. await generateServiceWorker(options2, viteConfig);
  485. }
  486. function _generateBundle({ options: options2, viteConfig, useImportRegister }, bundle) {
  487. if (options2.disable || !bundle)
  488. return;
  489. if (options2.manifest) {
  490. bundle[options2.manifestFilename] = {
  491. isAsset: true,
  492. type: "asset",
  493. name: void 0,
  494. source: generateWebManifestFile(options2),
  495. fileName: options2.manifestFilename
  496. };
  497. }
  498. if (options2.injectRegister === "auto")
  499. options2.injectRegister = useImportRegister ? null : "script";
  500. if (options2.injectRegister === "script" && !(0, import_fs3.existsSync)((0, import_path4.resolve)(viteConfig.publicDir, FILE_SW_REGISTER))) {
  501. bundle[FILE_SW_REGISTER] = {
  502. isAsset: true,
  503. type: "asset",
  504. name: void 0,
  505. source: generateSimpleSWRegister(options2, false),
  506. fileName: FILE_SW_REGISTER
  507. };
  508. }
  509. return bundle;
  510. }
  511. function createAPI(ctx) {
  512. return {
  513. get disabled() {
  514. var _a;
  515. return (_a = ctx == null ? void 0 : ctx.options) == null ? void 0 : _a.disable;
  516. },
  517. get pwaInDevEnvironment() {
  518. return (ctx == null ? void 0 : ctx.devEnvironment) === true;
  519. },
  520. webManifestData() {
  521. const options2 = ctx == null ? void 0 : ctx.options;
  522. if (!options2 || options2.disable || !options2.manifest || ctx.devEnvironment && !ctx.options.devOptions.enabled)
  523. return void 0;
  524. let url = options2.manifestFilename;
  525. let manifest;
  526. if (ctx.devEnvironment && ctx.options.devOptions.enabled === true) {
  527. url = ctx.options.devOptions.webManifestUrl ?? options2.manifestFilename;
  528. manifest = generateWebManifest(options2, true);
  529. } else {
  530. manifest = generateWebManifest(options2, false);
  531. }
  532. return {
  533. href: `${options2.base}${url}`,
  534. useCredentials: ctx.options.useCredentials,
  535. toLinkTag() {
  536. return manifest;
  537. }
  538. };
  539. },
  540. registerSWData() {
  541. const options2 = ctx == null ? void 0 : ctx.options;
  542. if (!options2 || options2.disable || ctx.devEnvironment && !ctx.options.devOptions.enabled)
  543. return void 0;
  544. const mode = options2.injectRegister;
  545. if (!mode || ctx.useImportRegister)
  546. return void 0;
  547. let type = "classic";
  548. let script;
  549. let shouldRegisterSW = options2.injectRegister === "inline" || options2.injectRegister === "script";
  550. if (ctx.devEnvironment && ctx.options.devOptions.enabled === true) {
  551. type = ctx.options.devOptions.type ?? "classic";
  552. script = generateRegisterDevSW();
  553. shouldRegisterSW = true;
  554. } else if (shouldRegisterSW) {
  555. script = generateRegisterSW(options2, false);
  556. }
  557. return {
  558. shouldRegisterSW,
  559. inline: options2.injectRegister === "inline",
  560. scope: options2.scope,
  561. inlinePath: `${options2.base}${ctx.devEnvironment ? DEV_SW_NAME : options2.filename}`,
  562. registerPath: `${options2.base}${FILE_SW_REGISTER}`,
  563. type,
  564. toScriptTag() {
  565. return script;
  566. }
  567. };
  568. },
  569. generateBundle(bundle) {
  570. return _generateBundle(ctx, bundle);
  571. },
  572. async generateSW() {
  573. return await _generateSW(ctx);
  574. },
  575. extendManifestEntries(fn) {
  576. const { options: options2 } = ctx;
  577. if (options2.disable)
  578. return;
  579. const configField = options2.strategies === "generateSW" ? "workbox" : "injectManifest";
  580. const result = fn(options2[configField].additionalManifestEntries || []);
  581. if (result != null)
  582. options2[configField].additionalManifestEntries = result;
  583. }
  584. };
  585. }
  586. // src/plugins/build.ts
  587. function BuildPlugin(ctx) {
  588. var _a, _b;
  589. return {
  590. name: "vite-plugin-pwa:build",
  591. enforce: "post",
  592. apply: "build",
  593. transformIndexHtml: {
  594. enforce: "post",
  595. transform(html) {
  596. const { options: options2, useImportRegister } = ctx;
  597. if (options2.disable)
  598. return html;
  599. if (options2.injectRegister === "auto")
  600. options2.injectRegister = useImportRegister ? null : "script";
  601. return injectServiceWorker(html, options2, false);
  602. }
  603. },
  604. generateBundle(_, bundle) {
  605. return _generateBundle(ctx, bundle);
  606. },
  607. closeBundle: {
  608. sequential: true,
  609. order: (_b = (_a = ctx.userOptions) == null ? void 0 : _a.integration) == null ? void 0 : _b.closeBundleOrder,
  610. async handler() {
  611. if (!ctx.viteConfig.build.ssr && !ctx.options.disable)
  612. await _generateSW(ctx);
  613. }
  614. },
  615. async buildEnd(error) {
  616. if (error)
  617. throw error;
  618. }
  619. };
  620. }
  621. // src/plugins/dev.ts
  622. var import_path5 = require("path");
  623. var import_fs4 = require("fs");
  624. // src/utils.ts
  625. function resolveBathPath(base) {
  626. if (isAbsolute(base))
  627. return base;
  628. return !base.startsWith("/") && !base.startsWith("./") ? `/${base}` : base;
  629. }
  630. function isAbsolute(url) {
  631. return url.match(/^(?:[a-z]+:)?\/\//i);
  632. }
  633. function normalizePath(path) {
  634. return path.replace(/\\/g, "/");
  635. }
  636. // src/plugins/dev.ts
  637. var swDevOptions = {
  638. swUrl: DEV_SW_NAME,
  639. swDevGenerated: false,
  640. workboxPaths: /* @__PURE__ */ new Map()
  641. };
  642. function DevPlugin(ctx) {
  643. return {
  644. name: "vite-plugin-pwa:dev-sw",
  645. apply: "serve",
  646. transformIndexHtml: {
  647. enforce: "post",
  648. async transform(html) {
  649. const { options: options2 } = ctx;
  650. if (options2.disable || !options2.manifest || !options2.devOptions.enabled)
  651. return html;
  652. html = injectServiceWorker(html, options2, true);
  653. return html.replace(
  654. "</body>",
  655. `${generateRegisterDevSW()}
  656. </body>`
  657. );
  658. }
  659. },
  660. configureServer(server) {
  661. ctx.devEnvironment = true;
  662. const { options: options2 } = ctx;
  663. if (!options2.disable && options2.manifest && options2.devOptions.enabled) {
  664. server.ws.on(DEV_READY_NAME, createSWResponseHandler(server, ctx));
  665. const name = options2.devOptions.webManifestUrl ?? `${options2.base}${options2.manifestFilename}`;
  666. server.middlewares.use((req, res, next) => {
  667. if (req.url === name) {
  668. res.statusCode = 200;
  669. res.setHeader("Content-Type", "application/manifest+json");
  670. res.write(generateWebManifestFile(options2), "utf-8");
  671. res.end();
  672. } else {
  673. next();
  674. }
  675. });
  676. }
  677. },
  678. resolveId(id) {
  679. if (id === DEV_SW_VIRTUAL)
  680. return RESOLVED_DEV_SW_VIRTUAL;
  681. const { options: options2 } = ctx;
  682. if (!options2.disable && options2.devOptions.enabled && options2.strategies === "injectManifest" && !options2.selfDestroying) {
  683. const name = id.startsWith("/") ? id.slice(1) : id;
  684. return name === swDevOptions.swUrl || name === options2.injectManifest.swSrc ? options2.injectManifest.swSrc : void 0;
  685. }
  686. return void 0;
  687. },
  688. async load(id) {
  689. if (id === RESOLVED_DEV_SW_VIRTUAL)
  690. return generateSWHMR();
  691. const { options: options2, viteConfig } = ctx;
  692. if (!options2.disable && options2.devOptions.enabled) {
  693. if (options2.strategies === "injectManifest" && !options2.selfDestroying) {
  694. const swSrc = normalizePath(options2.injectManifest.swSrc);
  695. if (id === swSrc) {
  696. let content = await import_fs4.promises.readFile(options2.injectManifest.swSrc, "utf-8");
  697. const resolvedIP = options2.injectManifest.injectionPoint;
  698. if (resolvedIP) {
  699. const ip = new RegExp(resolvedIP, "g");
  700. const navigateFallback = options2.devOptions.navigateFallback;
  701. if (navigateFallback)
  702. content = content.replace(ip, `[{ url: '${navigateFallback}' }]`);
  703. else
  704. content = content.replace(ip, "[]");
  705. }
  706. return content;
  707. }
  708. if (swDevOptions.workboxPaths.has(id))
  709. return await import_fs4.promises.readFile(swDevOptions.workboxPaths.get(id), "utf-8");
  710. return void 0;
  711. }
  712. if (id.endsWith(swDevOptions.swUrl)) {
  713. const globDirectory = (0, import_path5.resolve)(viteConfig.root, "dev-dist");
  714. if (!(0, import_fs4.existsSync)(globDirectory))
  715. (0, import_fs4.mkdirSync)(globDirectory);
  716. const swDest = (0, import_path5.resolve)(globDirectory, "sw.js");
  717. if (!swDevOptions.swDevGenerated || !(0, import_fs4.existsSync)(swDest)) {
  718. const navigateFallback = options2.workbox.navigateFallback;
  719. const { filePaths } = await generateServiceWorker(
  720. Object.assign(
  721. {},
  722. options2,
  723. {
  724. swDest: options2.selfDestroying ? swDest : options2.swDest,
  725. workbox: {
  726. ...options2.workbox,
  727. navigateFallbackAllowlist: options2.devOptions.navigateFallbackAllowlist ?? [/^\/$/],
  728. runtimeCaching: options2.devOptions.disableRuntimeConfig ? void 0 : options2.workbox.runtimeCaching,
  729. additionalManifestEntries: navigateFallback ? [navigateFallback] : void 0,
  730. cleanupOutdatedCaches: true,
  731. globDirectory: globDirectory.replace(/\\/g, "/"),
  732. swDest: swDest.replace(/\\/g, "/")
  733. }
  734. }
  735. ),
  736. viteConfig
  737. );
  738. filePaths.forEach((we) => {
  739. const name = (0, import_path5.basename)(we);
  740. if (name !== "sw.js")
  741. swDevOptions.workboxPaths.set(normalizePath(`${options2.base}${name}`), we);
  742. });
  743. swDevOptions.swDevGenerated = true;
  744. }
  745. return await import_fs4.promises.readFile(swDest, "utf-8");
  746. }
  747. const key = normalizePath(`${options2.base}${id.startsWith("/") ? id.slice(1) : id}`);
  748. if (swDevOptions.workboxPaths.has(key))
  749. return await import_fs4.promises.readFile(swDevOptions.workboxPaths.get(key), "utf-8");
  750. }
  751. }
  752. };
  753. }
  754. async function createDevRegisterSW(options2, viteConfig) {
  755. if (options2.injectRegister === "script") {
  756. const devDist = (0, import_path5.resolve)(viteConfig.root, "dev-dist");
  757. if (!(0, import_fs4.existsSync)(devDist))
  758. (0, import_fs4.mkdirSync)(devDist);
  759. const registerSW = (0, import_path5.resolve)(devDist, FILE_SW_REGISTER);
  760. if ((0, import_fs4.existsSync)(registerSW)) {
  761. if (!swDevOptions.workboxPaths.has(registerSW))
  762. swDevOptions.workboxPaths.set(normalizePath(`${options2.base}${FILE_SW_REGISTER}`), registerSW);
  763. return;
  764. }
  765. await import_fs4.promises.writeFile(registerSW, generateSimpleSWRegister(options2, true), { encoding: "utf8" });
  766. swDevOptions.workboxPaths.set(normalizePath(`${options2.base}${FILE_SW_REGISTER}`), registerSW);
  767. }
  768. }
  769. function createSWResponseHandler(server, ctx) {
  770. return async () => {
  771. const { options: options2, useImportRegister } = ctx;
  772. const { injectRegister, scope, base } = options2;
  773. if (!useImportRegister && injectRegister) {
  774. if (injectRegister === "auto")
  775. options2.injectRegister = "script";
  776. await createDevRegisterSW(options2, ctx.viteConfig);
  777. server.ws.send({
  778. type: "custom",
  779. event: DEV_REGISTER_SW_NAME,
  780. data: {
  781. inline: options2.injectRegister === "inline",
  782. scope,
  783. inlinePath: `${base}${DEV_SW_NAME}`,
  784. registerPath: `${base}${FILE_SW_REGISTER}`,
  785. swType: options2.devOptions.type
  786. }
  787. });
  788. }
  789. };
  790. }
  791. // src/options.ts
  792. var import_fs5 = __toESM(require("fs"));
  793. var import_path6 = require("path");
  794. function resolveSwPaths(injectManifest, root, srcDir, outDir, filename) {
  795. const swSrc = (0, import_path6.resolve)(root, srcDir, filename);
  796. if (injectManifest && (0, import_path6.extname)(filename) === ".ts" && import_fs5.default.existsSync(swSrc)) {
  797. const useFilename = `${filename.substring(0, filename.lastIndexOf("."))}.js`;
  798. return {
  799. swSrc,
  800. swDest: (0, import_path6.resolve)(root, outDir, useFilename),
  801. useFilename
  802. };
  803. }
  804. return {
  805. swSrc,
  806. swDest: (0, import_path6.resolve)(root, outDir, filename)
  807. };
  808. }
  809. async function resolveOptions(options2, viteConfig) {
  810. var _a;
  811. const root = viteConfig.root;
  812. const pkg = import_fs5.default.existsSync("package.json") ? JSON.parse(import_fs5.default.readFileSync("package.json", "utf-8")) : {};
  813. const {
  814. mode = process["env"]["NODE_ENV"] || "production",
  815. srcDir = "public",
  816. outDir = viteConfig.build.outDir || "dist",
  817. injectRegister = "auto",
  818. registerType = "prompt",
  819. filename = "sw.js",
  820. manifestFilename = "manifest.webmanifest",
  821. strategies = "generateSW",
  822. minify = true,
  823. base = viteConfig.base,
  824. includeAssets = void 0,
  825. includeManifestIcons = true,
  826. useCredentials = false,
  827. disable = false,
  828. devOptions = { enabled: false, type: "classic" },
  829. selfDestroying = false,
  830. integration = {}
  831. } = options2;
  832. const basePath = resolveBathPath(base);
  833. const { swSrc, swDest, useFilename } = resolveSwPaths(
  834. strategies === "injectManifest",
  835. root,
  836. srcDir,
  837. outDir,
  838. filename
  839. );
  840. const outDirRoot = (0, import_path6.resolve)(root, outDir);
  841. const scope = options2.scope || basePath;
  842. const defaultWorkbox = {
  843. swDest,
  844. globDirectory: outDirRoot,
  845. offlineGoogleAnalytics: false,
  846. cleanupOutdatedCaches: true,
  847. dontCacheBustURLsMatching: /[.-][a-f0-9]{8}\./,
  848. mode,
  849. navigateFallback: "index.html"
  850. };
  851. const defaultInjectManifest = {
  852. swSrc,
  853. swDest,
  854. globDirectory: outDirRoot,
  855. dontCacheBustURLsMatching: /[.-][a-f0-9]{8}\./,
  856. injectionPoint: "self.__WB_MANIFEST"
  857. };
  858. const defaultManifest = {
  859. name: pkg.name,
  860. short_name: pkg.name,
  861. start_url: basePath,
  862. display: "standalone",
  863. background_color: "#ffffff",
  864. lang: "en",
  865. scope
  866. };
  867. const workbox = Object.assign({}, defaultWorkbox, options2.workbox || {});
  868. const manifest = typeof options2.manifest === "boolean" && !options2.manifest ? false : Object.assign({}, defaultManifest, options2.manifest || {});
  869. const {
  870. vitePlugins = defaultInjectManifestVitePlugins,
  871. rollupFormat = "es",
  872. ...userInjectManifest
  873. } = options2.injectManifest || {};
  874. const injectManifest = Object.assign({}, defaultInjectManifest, userInjectManifest);
  875. if ((injectRegister === "auto" || injectRegister == null) && registerType === "autoUpdate") {
  876. workbox.skipWaiting = true;
  877. workbox.clientsClaim = true;
  878. }
  879. if (strategies === "generateSW" && workbox.sourcemap === void 0) {
  880. const sourcemap = (_a = viteConfig.build) == null ? void 0 : _a.sourcemap;
  881. workbox.sourcemap = sourcemap === true || sourcemap === "inline" || sourcemap === "hidden";
  882. }
  883. if (devOptions.enabled && viteConfig.command === "serve") {
  884. if (strategies === "generateSW")
  885. devOptions.type = "classic";
  886. } else {
  887. devOptions.enabled = false;
  888. devOptions.type = "classic";
  889. }
  890. const resolvedVitePWAOptions = {
  891. base: basePath,
  892. mode,
  893. swSrc,
  894. swDest,
  895. srcDir,
  896. outDir,
  897. injectRegister,
  898. registerType,
  899. filename: useFilename || filename,
  900. manifestFilename,
  901. strategies,
  902. workbox,
  903. manifest,
  904. useCredentials,
  905. injectManifest,
  906. scope,
  907. minify,
  908. includeAssets,
  909. includeManifestIcons,
  910. disable,
  911. integration,
  912. devOptions,
  913. rollupFormat,
  914. vitePlugins,
  915. selfDestroying
  916. };
  917. await configureStaticAssets(resolvedVitePWAOptions, viteConfig);
  918. return resolvedVitePWAOptions;
  919. }
  920. // src/plugins/main.ts
  921. function MainPlugin(ctx, api) {
  922. return {
  923. name: "vite-plugin-pwa",
  924. enforce: "pre",
  925. config() {
  926. return {
  927. ssr: {
  928. noExternal: ["workbox-window"]
  929. }
  930. };
  931. },
  932. async configResolved(config) {
  933. var _a, _b, _c;
  934. ctx.useImportRegister = false;
  935. ctx.viteConfig = config;
  936. (_c = (_b = (_a = ctx.userOptions) == null ? void 0 : _a.integration) == null ? void 0 : _b.configureOptions) == null ? void 0 : _c.call(_b, config, ctx.userOptions);
  937. ctx.options = await resolveOptions(ctx.userOptions, config);
  938. },
  939. resolveId(id) {
  940. return VIRTUAL_MODULES.includes(id) ? VIRTUAL_MODULES_RESOLVE_PREFIX + id : void 0;
  941. },
  942. load(id) {
  943. if (id.startsWith(VIRTUAL_MODULES_RESOLVE_PREFIX))
  944. id = id.slice(VIRTUAL_MODULES_RESOLVE_PREFIX.length);
  945. else
  946. return;
  947. if (VIRTUAL_MODULES.includes(id)) {
  948. ctx.useImportRegister = true;
  949. if (ctx.viteConfig.command === "serve" && ctx.options.devOptions.enabled) {
  950. return generateRegisterSW2(
  951. { ...ctx.options, filename: swDevOptions.swUrl },
  952. "build",
  953. VIRTUAL_MODULES_MAP[id]
  954. );
  955. } else {
  956. return generateRegisterSW2(
  957. ctx.options,
  958. !ctx.options.disable && ctx.viteConfig.command === "build" ? "build" : "dev",
  959. VIRTUAL_MODULES_MAP[id]
  960. );
  961. }
  962. }
  963. },
  964. api
  965. };
  966. }
  967. // src/plugins/info.ts
  968. function InfoPlugin(ctx, api) {
  969. return {
  970. name: "vite-plugin-pwa:info",
  971. enforce: "post",
  972. resolveId(id) {
  973. if (id === PWA_INFO_VIRTUAL)
  974. return RESOLVED_PWA_INFO_VIRTUAL;
  975. return void 0;
  976. },
  977. load(id) {
  978. if (id === RESOLVED_PWA_INFO_VIRTUAL)
  979. return generatePwaInfo(ctx, api);
  980. }
  981. };
  982. }
  983. function generatePwaInfo(ctx, api) {
  984. const webManifestData = api.webManifestData();
  985. if (!webManifestData)
  986. return "export const pwaInfo = undefined;";
  987. const { href, useCredentials, toLinkTag } = webManifestData;
  988. const registerSWData = api.registerSWData();
  989. const entry = {
  990. pwaInDevEnvironment: api.pwaInDevEnvironment,
  991. webManifest: {
  992. href,
  993. useCredentials,
  994. linkTag: toLinkTag()
  995. }
  996. };
  997. if (registerSWData) {
  998. const scriptTag = registerSWData.toScriptTag();
  999. if (scriptTag) {
  1000. const { inline, inlinePath, registerPath, type, scope } = registerSWData;
  1001. entry.registerSW = {
  1002. inline,
  1003. inlinePath,
  1004. registerPath,
  1005. type,
  1006. scope,
  1007. scriptTag
  1008. };
  1009. }
  1010. }
  1011. return `export const pwaInfo = ${JSON.stringify(entry)};`;
  1012. }
  1013. // src/cache.ts
  1014. var cachePreset = [
  1015. {
  1016. urlPattern: /^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
  1017. handler: "CacheFirst",
  1018. options: {
  1019. cacheName: "google-fonts",
  1020. expiration: {
  1021. maxEntries: 4,
  1022. maxAgeSeconds: 365 * 24 * 60 * 60
  1023. }
  1024. }
  1025. },
  1026. {
  1027. urlPattern: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
  1028. handler: "StaleWhileRevalidate",
  1029. options: {
  1030. cacheName: "static-font-assets",
  1031. expiration: {
  1032. maxEntries: 4,
  1033. maxAgeSeconds: 7 * 24 * 60 * 60
  1034. }
  1035. }
  1036. },
  1037. {
  1038. urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
  1039. handler: "StaleWhileRevalidate",
  1040. options: {
  1041. cacheName: "static-image-assets",
  1042. expiration: {
  1043. maxEntries: 64,
  1044. maxAgeSeconds: 24 * 60 * 60
  1045. }
  1046. }
  1047. },
  1048. {
  1049. urlPattern: /\.(?:js)$/i,
  1050. handler: "StaleWhileRevalidate",
  1051. options: {
  1052. cacheName: "static-js-assets",
  1053. expiration: {
  1054. maxEntries: 32,
  1055. maxAgeSeconds: 24 * 60 * 60
  1056. }
  1057. }
  1058. },
  1059. {
  1060. urlPattern: /\.(?:css|less)$/i,
  1061. handler: "StaleWhileRevalidate",
  1062. options: {
  1063. cacheName: "static-style-assets",
  1064. expiration: {
  1065. maxEntries: 32,
  1066. maxAgeSeconds: 24 * 60 * 60
  1067. }
  1068. }
  1069. },
  1070. {
  1071. urlPattern: /\.(?:json|xml|csv)$/i,
  1072. handler: "NetworkFirst",
  1073. options: {
  1074. cacheName: "static-data-assets",
  1075. expiration: {
  1076. maxEntries: 32,
  1077. maxAgeSeconds: 24 * 60 * 60
  1078. }
  1079. }
  1080. },
  1081. {
  1082. urlPattern: /\/api\/.*$/i,
  1083. handler: "NetworkFirst",
  1084. method: "GET",
  1085. options: {
  1086. cacheName: "apis",
  1087. expiration: {
  1088. maxEntries: 16,
  1089. maxAgeSeconds: 24 * 60 * 60
  1090. },
  1091. networkTimeoutSeconds: 10
  1092. }
  1093. },
  1094. {
  1095. urlPattern: /.*/i,
  1096. handler: "NetworkFirst",
  1097. options: {
  1098. cacheName: "others",
  1099. expiration: {
  1100. maxEntries: 32,
  1101. maxAgeSeconds: 24 * 60 * 60
  1102. },
  1103. networkTimeoutSeconds: 10
  1104. }
  1105. }
  1106. ];
  1107. // src/index.ts
  1108. function VitePWA(userOptions = {}) {
  1109. const ctx = createContext(userOptions);
  1110. const api = createAPI(ctx);
  1111. return [
  1112. MainPlugin(ctx, api),
  1113. InfoPlugin(ctx, api),
  1114. BuildPlugin(ctx),
  1115. DevPlugin(ctx)
  1116. ];
  1117. }
  1118. // Annotate the CommonJS export names for ESM import in node:
  1119. 0 && (module.exports = {
  1120. VitePWA,
  1121. cachePreset,
  1122. defaultInjectManifestVitePlugins
  1123. });