crxjs / chrome-extension-tools

Bundling Chrome Extensions can be pretty complex. It doesn't have to be.
https://crxjs.dev/vite-plugin
2.9k stars 192 forks source link

Support for file relocation plugin #647

Closed thdoan closed 1 year ago

thdoan commented 1 year ago

Describe the problem

I'm currently using this plugin to move dist/src/popup/index.html to dist/popup.html:

vite-rename-file.js

export const renameFile = (source, destination) => {
  if (typeof source !== 'string' || typeof destination !== 'string') {
    return
  }

  return {
    name: 'rename-file',
    enforce: 'post',
    generateBundle(options, bundle) {
      bundle[source].fileName = destination;
    },
  }
};

vite.config.ts

import { crx } from '@crxjs/vite-plugin';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { resolve } from 'path';
import { defineConfig } from 'vite';
import { renameFile } from './src/lib/vite-rename-file.js';
import manifest from './manifest.json';

export default defineConfig({
  plugins: [
    svelte(),
    crx({ manifest }),
    renameFile('src/popup/index.html', 'popup.html')
  ],
  publicDir: 'static',
  resolve: {
    alias: {
      src: resolve(__dirname, 'src'),
    },
  },
});

This successfully builds dist/popup.html, however the extension cannot load because manifest.json still has the old path ("default_popup": "src/popup/index.html",). How would I get manifest.json to output "default_popup": "popup.html",?

Describe the proposed solution

I'm not familiar enough with this plugin to offer a solution. Maybe a solution already exists?

Alternatives considered

None that I'm aware of.

Importance

nice to have

dbjpanda commented 1 year ago

@thdoan Did you find any resolution?

jacksteamdev commented 1 year ago

CRXJS plugins are possible, in fact, CRXJS is a collection of plugins with special hooks.

Plugins are not documented yet, as I haven't had time to finalize a public plugin API. You can look at the types here.

Basic plugin instructions

  1. (optional) Use type CrxPlugin from @crxjs/vite-plugin
  2. (required) Prefix the plugin name with crx: so CRXJS uses the CRXJS hooks
  3. Use transformCrxManifest or renderCrxManifest hooks to modify the manifest
    • transformCrxManifest modifies the input manifest at the beginning of the transform hook
    • renderCrxManifest modifies the output manifest at the end of the generateBundle hook

You can add a CRXJS hook to a plugin like this:

export const renameFile = (source, destination): CrxPlugin => {
  if (typeof source !== 'string' || typeof destination !== 'string') {
    return
  }

  return {
    name: 'crx:rename-file',
    enforce: 'post',
    generateBundle(options, bundle) {
      bundle[source].fileName = destination;
    },
    renderCrxManifest(manifest) {
      manifest.short_name = "with renamed files";
      return manifest;
    },
  }
};
jacksteamdev commented 1 year ago

I've opened an RFC for an official plugin API: https://github.com/crxjs/chrome-extension-tools/discussions/652

thdoan commented 1 year ago

@jacksteamdev thank you for the assist. @dbjpanda here's how I renamed dist/src/popup/popup.html to dist/popup.html:

vite.config.ts

import { crx, CrxPlugin } from '@crxjs/vite-plugin';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { resolve } from 'path';
import { defineConfig } from 'vite';
import manifest from './manifest.json';

const renameFile = (source, destination): CrxPlugin => {
  if (typeof source !== 'string' || typeof destination !== 'string') {
    return;
  }

  return {
    name: 'crx:rename-file',
    enforce: 'post',
    generateBundle(options, bundle) {
      bundle[source].fileName = destination;
    },
    renderCrxManifest(manifest) {
      manifest.action.default_popup = destination;
      return manifest;
    },
  };
};

export default defineConfig({
  plugins: [
    svelte(),
    crx({ manifest }),
    renameFile('src/popup/popup.html', 'popup.html')
  ],
  resolve: {
    alias: {
      src: resolve(__dirname, 'src'),
    },
  },
});
thdoan commented 1 year ago

UPDATE: @jacksteamdev vite build works perfectly with the CRXJS plugin above, but I just noticed that when I run vite to start the dev server, it throws this error:

image

Would you happen to know how to resolve this?

thdoan commented 1 year ago

The issue above was resolved. It was caused by an HTML file that was not referenced in manifest.json, so I had to add this extra configuration: https://crxjs.dev/vite-plugin/concepts/pages

Razboy20 commented 1 year ago

@thdoan Quick question, how were you able to resolve the "cannot set properties of undefined" error; following https://crxjs.dev/vite-plugin/concepts/pages did not seem to remove the error.