inject-manifest.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. "use strict";
  2. /*
  3. Copyright 2018 Google LLC
  4. Use of this source code is governed by an MIT-style
  5. license that can be found in the LICENSE file or at
  6. https://opensource.org/licenses/MIT.
  7. */
  8. var __importDefault = (this && this.__importDefault) || function (mod) {
  9. return (mod && mod.__esModule) ? mod : { "default": mod };
  10. };
  11. Object.defineProperty(exports, "__esModule", { value: true });
  12. exports.injectManifest = void 0;
  13. const assert_1 = __importDefault(require("assert"));
  14. const fs_extra_1 = __importDefault(require("fs-extra"));
  15. const fast_json_stable_stringify_1 = __importDefault(require("fast-json-stable-stringify"));
  16. const upath_1 = __importDefault(require("upath"));
  17. const errors_1 = require("./lib/errors");
  18. const escape_regexp_1 = require("./lib/escape-regexp");
  19. const get_file_manifest_entries_1 = require("./lib/get-file-manifest-entries");
  20. const get_source_map_url_1 = require("./lib/get-source-map-url");
  21. const rebase_path_1 = require("./lib/rebase-path");
  22. const replace_and_update_source_map_1 = require("./lib/replace-and-update-source-map");
  23. const translate_url_to_sourcemap_paths_1 = require("./lib/translate-url-to-sourcemap-paths");
  24. const validate_options_1 = require("./lib/validate-options");
  25. /**
  26. * This method creates a list of URLs to precache, referred to as a "precache
  27. * manifest", based on the options you provide.
  28. *
  29. * The manifest is injected into the `swSrc` file, and the placeholder string
  30. * `injectionPoint` determines where in the file the manifest should go.
  31. *
  32. * The final service worker file, with the manifest injected, is written to
  33. * disk at `swDest`.
  34. *
  35. * This method will not compile or bundle your `swSrc` file; it just handles
  36. * injecting the manifest.
  37. *
  38. * ```
  39. * // The following lists some common options; see the rest of the documentation
  40. * // for the full set of options and defaults.
  41. * const {count, size, warnings} = await injectManifest({
  42. * dontCacheBustURLsMatching: [new RegExp('...')],
  43. * globDirectory: '...',
  44. * globPatterns: ['...', '...'],
  45. * maximumFileSizeToCacheInBytes: ...,
  46. * swDest: '...',
  47. * swSrc: '...',
  48. * });
  49. * ```
  50. *
  51. * @memberof workbox-build
  52. */
  53. async function injectManifest(config) {
  54. const options = (0, validate_options_1.validateInjectManifestOptions)(config);
  55. // Make sure we leave swSrc and swDest out of the precache manifest.
  56. for (const file of [options.swSrc, options.swDest]) {
  57. options.globIgnores.push((0, rebase_path_1.rebasePath)({
  58. file,
  59. baseDirectory: options.globDirectory,
  60. }));
  61. }
  62. const globalRegexp = new RegExp((0, escape_regexp_1.escapeRegExp)(options.injectionPoint), 'g');
  63. const { count, size, manifestEntries, warnings } = await (0, get_file_manifest_entries_1.getFileManifestEntries)(options);
  64. let swFileContents;
  65. try {
  66. swFileContents = await fs_extra_1.default.readFile(options.swSrc, 'utf8');
  67. }
  68. catch (error) {
  69. throw new Error(`${errors_1.errors['invalid-sw-src']} ${error instanceof Error && error.message ? error.message : ''}`);
  70. }
  71. const injectionResults = swFileContents.match(globalRegexp);
  72. // See https://github.com/GoogleChrome/workbox/issues/2230
  73. const injectionPoint = options.injectionPoint ? options.injectionPoint : '';
  74. if (!injectionResults) {
  75. if (upath_1.default.resolve(options.swSrc) === upath_1.default.resolve(options.swDest)) {
  76. throw new Error(`${errors_1.errors['same-src-and-dest']} ${injectionPoint}`);
  77. }
  78. throw new Error(`${errors_1.errors['injection-point-not-found']} ${injectionPoint}`);
  79. }
  80. (0, assert_1.default)(injectionResults.length === 1, `${errors_1.errors['multiple-injection-points']} ${injectionPoint}`);
  81. const manifestString = (0, fast_json_stable_stringify_1.default)(manifestEntries);
  82. const filesToWrite = {};
  83. const url = (0, get_source_map_url_1.getSourceMapURL)(swFileContents);
  84. // See https://github.com/GoogleChrome/workbox/issues/2957
  85. const { destPath, srcPath, warning } = (0, translate_url_to_sourcemap_paths_1.translateURLToSourcemapPaths)(url, options.swSrc, options.swDest);
  86. if (warning) {
  87. warnings.push(warning);
  88. }
  89. // If our swSrc file contains a sourcemap, we would invalidate that
  90. // mapping if we just replaced injectionPoint with the stringified manifest.
  91. // Instead, we need to update the swDest contents as well as the sourcemap
  92. // (assuming it's a real file, not a data: URL) at the same time.
  93. // See https://github.com/GoogleChrome/workbox/issues/2235
  94. // and https://github.com/GoogleChrome/workbox/issues/2648
  95. if (srcPath && destPath) {
  96. const originalMap = (await fs_extra_1.default.readJSON(srcPath, {
  97. encoding: 'utf8',
  98. }));
  99. const { map, source } = await (0, replace_and_update_source_map_1.replaceAndUpdateSourceMap)({
  100. originalMap,
  101. jsFilename: upath_1.default.basename(options.swDest),
  102. originalSource: swFileContents,
  103. replaceString: manifestString,
  104. searchString: options.injectionPoint,
  105. });
  106. filesToWrite[options.swDest] = source;
  107. filesToWrite[destPath] = map;
  108. }
  109. else {
  110. // If there's no sourcemap associated with swSrc, a simple string
  111. // replacement will suffice.
  112. filesToWrite[options.swDest] = swFileContents.replace(globalRegexp, manifestString);
  113. }
  114. for (const [file, contents] of Object.entries(filesToWrite)) {
  115. try {
  116. await fs_extra_1.default.mkdirp(upath_1.default.dirname(file));
  117. }
  118. catch (error) {
  119. throw new Error(errors_1.errors['unable-to-make-sw-directory'] +
  120. ` '${error instanceof Error && error.message ? error.message : ''}'`);
  121. }
  122. await fs_extra_1.default.writeFile(file, contents);
  123. }
  124. return {
  125. count,
  126. size,
  127. warnings,
  128. // Use upath.resolve() to make all the paths absolute.
  129. filePaths: Object.keys(filesToWrite).map((f) => upath_1.default.resolve(f)),
  130. };
  131. }
  132. exports.injectManifest = injectManifest;