make-manifest-plugin.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import fs from 'node:fs';
  2. import { resolve } from 'node:path';
  3. import { pathToFileURL } from 'node:url';
  4. import process from 'node:process';
  5. import { colorLog, ManifestParser } from '@extension/dev-utils';
  6. import type { PluginOption } from 'vite';
  7. import type { Manifest } from '@extension/dev-utils/dist/lib/manifest-parser/type';
  8. const rootDir = resolve(__dirname, '..', '..');
  9. const refreshFile = resolve(__dirname, '..', 'refresh.js');
  10. const manifestFile = resolve(rootDir, 'manifest.js');
  11. const getManifestWithCacheBurst = (): Promise<{ default: chrome.runtime.ManifestV3 }> => {
  12. const withCacheBurst = (path: string) => `${path}?${Date.now().toString()}`;
  13. /**
  14. * In Windows, import() doesn't work without file:// protocol.
  15. * So, we need to convert path to file:// protocol. (url.pathToFileURL)
  16. */
  17. if (process.platform === 'win32') {
  18. return import(withCacheBurst(pathToFileURL(manifestFile).href));
  19. }
  20. return import(withCacheBurst(manifestFile));
  21. };
  22. export default function makeManifestPlugin(config: { outDir: string }): PluginOption {
  23. function makeManifest(manifest: chrome.runtime.ManifestV3, to: string) {
  24. if (!fs.existsSync(to)) {
  25. fs.mkdirSync(to);
  26. }
  27. const manifestPath = resolve(to, 'manifest.json');
  28. const isFirefox = process.env.__FIREFOX__ === 'true';
  29. const isDev = process.env.__DEV__ === 'true';
  30. if (isDev) {
  31. addRefreshContentScript(manifest);
  32. }
  33. fs.writeFileSync(manifestPath, ManifestParser.convertManifestToString(manifest, isFirefox ? 'firefox' : 'chrome'));
  34. if (isDev) {
  35. fs.copyFileSync(refreshFile, resolve(to, 'refresh.js'));
  36. }
  37. colorLog(`Manifest file copy complete: ${manifestPath}`, 'success');
  38. }
  39. return {
  40. name: 'make-manifest',
  41. buildStart() {
  42. this.addWatchFile(manifestFile);
  43. },
  44. async writeBundle() {
  45. const outDir = config.outDir;
  46. const manifest = await getManifestWithCacheBurst();
  47. makeManifest(manifest.default, outDir);
  48. },
  49. };
  50. }
  51. function addRefreshContentScript(manifest: Manifest) {
  52. manifest.content_scripts = manifest.content_scripts || [];
  53. manifest.content_scripts.push({
  54. matches: ['http://*/*', 'https://*/*', '<all_urls>'],
  55. js: ['refresh.js'], // for public's HMR(refresh) support
  56. });
  57. }