aklinker1 / vite-plugin-web-extension

Vite plugin for developing Chrome/Web Extensions
https://vite-plugin-web-extension.aklinker1.io/
MIT License
541 stars 47 forks source link

Cannot configure filename output patterns #128

Open filips123 opened 1 year ago

filips123 commented 1 year ago

Summary

Some options defined in scriptViteConfig and htmlViteConfig, specifically build.rollupOptions, get overwritten by vite-plugin-web-extension's own options. Additionally, changing filename patterns can make the build fail. This makes setting custom output patterns harder.

I would like to customize output patterns for some files. Specifically, to remove src prefix from HTML files, to have CSS and JS files in the same directory and the same filename as HTML file, while third-party/vendor/shared files should be in another directory. However, even after setting build.rollupOptions.output inside scriptViteConfig and htmlViteConfig, some patterns are not respected.

The file layout that I would like is something like this, in case this is relevant:

dist
├─── assets (or something similar)
│   ├─── some shared file.js
│   └─── another shared file.css
│
├───icons
|
├───mypath (directory where HTMl file is in source)
│   ├─── myfile.html
│   ├─── myfile.js
│   └─── myfile.css
|
├─── manifest.json
├─── background.js
└─── other stuff

It seems (part of the) problem is that user option can get overwritten here and here, possibly also on other places. I don't know if this is intentional, but if it is, I think there should be another way to provide a custom output config.

Reproduction

I have a mostly empty template for Vue with TypeScript, with the following modifications to vite.config.ts:

import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
import webExtension, { readJsonFile } from 'vite-plugin-web-extension'

function generateManifest () {
  const manifest = readJsonFile('src/manifest.json')
  const pkg = readJsonFile('package.json')
  return {
    name: pkg.name,
    description: pkg.description,
    version: pkg.version,
    ...manifest
  }
}

export default defineConfig({
  plugins: [
    vue(),
    webExtension({
      manifest: generateManifest,
      watchFilePaths: ['package.json', 'manifest.json'],
      browser: 'firefox',
      scriptViteConfig: {
        build: {
          rollupOptions: {
            output: {
              assetFileNames: 'script/asset/[name].[ext]',
              entryFileNames: 'script/entry/[name].js',
              chunkFileNames: 'script/chunk/[name].js'
            }
          }
        }
      },
      htmlViteConfig: {
        build: {
          rollupOptions: {
            output: {
              assetFileNames: 'html/asset/[name].[ext]',
              entryFileNames: 'html/entry/[name].js',
              chunkFileNames: 'html/chunk/[name].js'
            }
          }
        }
      }
    })
  ],
  build: {
    rollupOptions: {
      output: {
        assetFileNames: 'base/asset/[name].[ext]',
        entryFileNames: 'base/entry/[name].js',
        chunkFileNames: 'base/chunk/[name].js'
      }
    }
  }
})

All of these options are set just for testing, I haven't yet configured all the patterns that I want. The same problem happens if I only use the root's build or only the build defined in the plugin.

The first problem is that my custom fileNames patterns are not respected for all files (CSS files are still in the root directory):

dist
│   icon-with-shadow.svg
│   popup.css
│
├───icon
│       128.png
│       16.png
│       32.png
│       48.png
│       96.png
│
├───script
│   └───entry
│           background.js
│
└───src
        popup.html
        popup.js

The second problem is that the build fails with:

[web-extension:manifest] Entrypoint output for src/background.ts (src/background.js) not found

If I manually edit the plugin's code to remove its output definitions, more filename patterns (for CSS files) are respected:

dist
│   icon-with-shadow.svg
│
├───html
│   ├───asset
│   │       popup.css
│   │
│   └───entry
│       └───src
│               popup.js
│
├───icon
│       128.png
│       16.png
│       32.png
│       48.png
│       96.png
│
├───script
│   └───entry
│           background.js
│
└───src
        popup.html

But the build still fails.

Environment

  System:
    OS: Windows 10 10.0.19045
    CPU: (12) x64 AMD Ryzen 5 2600X Six-Core Processor
    Memory: 45.63 GB / 63.95 GB
  Binaries:
    Node: 16.20.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD
    npm: 9.3.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.6.6 - C:\Program Files\nodejs\pnpm.CMD
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (114.0.1823.67)
  npmPackages:
    vite: ^4.1.4 => 4.4.2
    vite-plugin-web-extension: ^3.0.1 => 3.1.1
aklinker1 commented 12 months ago

@filips123 It was intentional at the time to prevent people from accidentally causing file conflicts, but it has been reported several times, so I think I'll make it configurable. Should be as simple as flipping the parameters of vite.mergeConfig in a few places.

I'll try and get to it this week.

aklinker1 commented 11 months ago

Alright, working on this now, but a couple of comments:

The first problem is that my custom fileNames patterns are not respected for all files (CSS files are still in the root directory)

Even if you set customassetFileNames, entryFileNames, and chunkFileNames options, Vite will not respect your options for all files. Specifically, HTML files are ignored, like you noted. You can see this by creating a regular vite project and setting the options there.

If you want to fully customize the bundle output, you will need to write a custom plugin, like this one, https://github.com/aklinker1/wxt/blob/main/src/core/vite-plugins/multipageMove.ts, that updates the bundle and moves the files in the output directory.

The second problem is that the build fails with...

This is a bug, I'll fix it.