samrum / vite-plugin-web-extension

A vite plugin for generating cross browser platform, ES module based web extensions.
MIT License
323 stars 33 forks source link

Feature Request: `additionalInputs` paths outside of project root, globs, and additional options #109

Open jhildenbiddle opened 1 year ago

jhildenbiddle commented 1 year ago

First, thank you for the excellent project. I was looking an HMR solution for extension development, stumbled on this one, and have been very pleased with the results. Much appreciated.

Summary

Ideally, the additionalInputs option would:

  1. Handle files outside of the extension root directory
  2. Handle globs for files referenced in additionalInputs
  3. Support options similar to copy-related plugins like rollup-plugin-copy or vite-plugin-static-copy (which is based on the former plugin) to set the file destination within /dist, flatten directories, rename files, etc.

Use Case

I have a monorepo containing an extension generated by this project stored in an /extension directory. The extension requires files accessed via the parent directory. For example, I'd like to include files from /files directory in the directory structure below:

.
├── extension
│   ├── src
│   │   ├── assets
│   │   ├── entries
│   │   └── manifest.js
│   ├── package.json
│   └── vite.config.js
├── files
│   ├── file1.js
│   ├── file2.js
│   ├── file3.js
│   └── ...
└── package.json

I hoped I could use the additionalInputs option to watch/copy these files to /dist, add them to the web_accessible_resources section in manifest.json automatically, and have that work for both a build and development using HMR:

webExtension({
    manifest: getManifest(),
    additionalInputs: {
        scripts: ['../files/file1.js'],
    },
})

Unfortunately, using paths outside of the extension root results in the following error:

Invalid substitution "../files/file" for placeholder "[name]" in "output.entryFileNames" pattern, can be neither absolute nor relative path.

I've tried several other approaches to using files outside of the extension root, but they all have issues:

I can cobble a solution together, but it will be a much less elegant since the additionalInputs option does exactly what I need except it currently does not work with files outside of the extension root.

Proposed Enhancements

Given the same directory structure shown above, I'd like to use a glob pattern to reference all of the files in the /files directory:

webExtension({
  manifest: getManifest(),
  additionalInputs: {
    scripts: ['../files/*.js'],
  },
});

This would expect this to produce the following:

.
└── extension
    └── dist
        ├── ...
        ├── manifest.json
        └── files
            ├── file1.js
            ├── file2.js
            └── file3.js
"web_accessible_resources": [
  {
    "resources": ["files/*.js"],
    "matches": ["*://*/*"],
  },
],

If options similar to the ones found in rollup-plugin-copy or vite-plugin-static-copy were added, the additionalInputs configuration could look something like this:

webExtension({
  manifest: getManifest(),
  additionalInputs: {
    scripts: [
      {
        src: '../files/*.js',
        dest: 'foo/bar',
        flatten: true,
        rename: (name, extension, fullPath) => `renamed-${name}.${extension}`
      },
    ],
  },
});
.
└── extension
    └── dist
        ├── ...
        ├── manifest.json
        └── foo
            └── bar
                ├── renamed-file1.js
                ├── renamed-file2.js
                └── renamed-file3.js

Thanks in advance for your consideration. I'm happy discuss in more detail and contribute to the effort if you believe this would be worth doing.

samrum commented 1 year ago

Thanks for the detailed request!

  1. I'm somewhat in favor of handling files outside of the root directory, but I'd want to double check what Vite's stance on something like that is. I don't think you're normally able to import/pull files outside of the root of the project (or its dependencies) for security reasons, but I could be wrong.
  2. I'd agree with supporting glob patterns for additionalInputs. Though your expected web_accessible_resources are more likely to be the parsed glob inputs as opposed to carrying over the glob pattern itself since the pattern syntax will probably be different than what web_accessible_resource supports. With the plugin's optimizeWebAccessibleResources option they should still end up combined into a single entry, though.
  3. Instead of this, I'd rather ensure that existing vite/rollup options for modifying output filenames (rollupOptions.output.assetFileNames, rollupOptions.output.chunkFileNames, rollupOptions.output.entryFileNames) fully work if they aren't already. additionInputs are treated as rollup inputs, so those should be being applied to them.
jhildenbiddle commented 1 year ago

All sounds reasonable to me, @samrum.

One clarification worth making is that the files I'd like to include outside of the web extension root (the "external" files) are static files. Specifically, these files are loaded via dynamic import so there are no static imports referencing files outside of the extension root for Vite to trip on while bundling. The goal is to just make the files available to the extension like other web_accessible_resources files (i.e., watch the files, copy (build) or update (dev) when a change is detected, and modify the manifest accordingly).

I realize this doesn't cover every possible scenario that involves files outside of the extension root, but I thought it was worth clarifying in case it simplifies to problem.