aklinker1 / vite-plugin-web-extension

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

Getting infinite loop and 'Invalid substitution ... for placeholder "[name]" in "output.entryFilesNames" pattern' error #56

Closed carterworks closed 1 year ago

carterworks commented 1 year ago

I'm trying to migrate an existing extension to vite using this plugin.

However, when I run vite build, I get the following output

Full output

vite v4.0.1 building for production...
[vite-plugin-web-extension] Building for browser: chrome
[vite-plugin-web-extension] Building with vite config: {
  build: {
    outDir: '$PROJECT_DIR/dist',
    emptyOutDir: false,
    rollupOptions: { output: [Object] }
  },
  plugins: [
    [ [Object], [Object], false ],
    {
      name: 'vite-plugin-web-extension',
      config: [Function: config],
      configResolved: [Function: configResolved],
      buildStart: [AsyncFunction: buildStart],
      buildEnd: [AsyncFunction: buildEnd],
      closeBundle: [AsyncFunction: closeBundle]
    }
  ],
  resolve: {
    alias: {
      '~': '$PROJECT_DIR',
      src: '$PROJECT_DIR/src',
      app: '$PROJECT_DIR/src/app',
      shared: '$PROJECT_DIR/src/shared'
    },
    dedupe: [ 'react', 'react-dom' ]
  },
  optimizeDeps: { force: undefined },
  esbuild: {
    logOverride: { 'this-is-undefined-in-esm': 'silent' },
    jsx: 'transform',
    jsxImportSource: undefined,
    jsxSideEffects: false
  },
  server: { port: 3000, hmr: { host: 'localhost' } }
}
[vite-plugin-web-extension] Manifest before browser transform: {
  "name": "__MSG_appName__",
  "version": "1.4.1",
  "manifest_version": 2,
  "description": "__MSG_appDescription__",
  "icons": {
    "16": "icons/icon_16.png",
    "48": "icons/icon_48.png",
    "128": "icons/icon_128.png"
  },
  "minimum_chrome_version": "68.0.0",
  "default_locale": "en",
  "background": {
    "service_worker": "src/background/sw.js"
  },
  "browser_action": {
    "default_icon": {
      "16": "icons/icon_16.png",
      "48": "icons/icon_48.png",
      "128": "icons/icon_128.png"
    },
    "default_title": "__MSG_appName__"
  },
  "content_scripts": [
    {
      "matches": [
        "http://*/*",
        "https://*/*"
      ],
      "exclude_matches": [
        "http://*/*.xml",
        "https://*/*.xml"
      ],
      "js": [
        "src/content/content.js"
      ],
      "run_at": "document_start"
    }
  ],
  "permissions": [
    "cookies",
    "debugger",
    "storage",
    "webNavigation",
    "webRequest",
    "webRequestBlocking",
    "http://*/*",
    "https://*/*"
  ],
  "web_accessible_resources": [
    "src/app/index.html",
    "src/login/login.html"
  ],
  "content_security_policy": "script-src 'self'; object-src 'self'"
}
[vite-plugin-web-extension] Manifest after browser transform: {
  "name": "__MSG_appName__",
  "version": "1.4.1",
  "manifest_version": 2,
  "description": "__MSG_appDescription__",
  "icons": {
    "16": "icons/icon_16.png",
    "48": "icons/icon_48.png",
    "128": "icons/icon_128.png"
  },
  "minimum_chrome_version": "68.0.0",
  "default_locale": "en",
  "background": {
    "service_worker": "src/background/sw.js"
  },
  "browser_action": {
    "default_icon": {
      "16": "icons/icon_16.png",
      "48": "icons/icon_48.png",
      "128": "icons/icon_128.png"
    },
    "default_title": "__MSG_appName__"
  },
  "content_scripts": [
    {
      "matches": [
        "http://*/*",
        "https://*/*"
      ],
      "exclude_matches": [
        "http://*/*.xml",
        "https://*/*.xml"
      ],
      "js": [
        "src/content/content.js"
      ],
      "run_at": "document_start"
    }
  ],
  "permissions": [
    "cookies",
    "debugger",
    "storage",
    "webNavigation",
    "webRequest",
    "webRequestBlocking",
    "http://*/*",
    "https://*/*"
  ],
  "web_accessible_resources": [
    "src/app/index.html",
    "src/login/login.html"
  ],
  "content_security_policy": "script-src 'self'; object-src 'self'"
}
[vite-plugin-web-extension] Searching for assets in: icons
[vite-plugin-web-extension]   > icons/icon_128.png
[vite-plugin-web-extension]   > icons/icon_16.png
[vite-plugin-web-extension]   > icons/icon_48.png
[vite-plugin-web-extension] Final manifest: {
  "name": "__MSG_appName__",
  "version": "1.4.1",
  "manifest_version": 2,
  "description": "__MSG_appDescription__",
  "icons": {
    "16": "icons/icon_16.png",
    "48": "icons/icon_48.png",
    "128": "icons/icon_128.png"
  },
  "minimum_chrome_version": "68.0.0",
  "default_locale": "en",
  "background": {
    "service_worker": "src/background/sw.js"
  },
  "browser_action": {
    "default_icon": {
      "16": "icons/icon_16.png",
      "48": "icons/icon_48.png",
      "128": "icons/icon_128.png"
    },
    "default_title": "__MSG_appName__"
  },
  "content_scripts": [
    {
      "matches": [
        "http://*/*",
        "https://*/*"
      ],
      "exclude_matches": [
        "http://*/*.xml",
        "https://*/*.xml"
      ],
      "js": [
        "src/content/content.js"
      ],
      "run_at": "document_start"
    }
  ],
  "permissions": [
    "cookies",
    "debugger",
    "storage",
    "webNavigation",
    "webRequest",
    "webRequestBlocking",
    "http://*/*",
    "https://*/*"
  ],
  "web_accessible_resources": [
    "src/app/index.html",
    "src/login/login.html"
  ],
  "content_security_policy": "script-src 'self'; object-src 'self'"
}
[vite-plugin-web-extension] Final rollup inputs: {
  '$PROJECT_DIR/src/app/index': '$PROJECT_DIR/src/app/index.html',
  '$PROJECT_DIR/src/login/login': '$PROJECT_DIR/src/login/login.html'
}

[vite-plugin-web-extension] 
  Building HTML Pages in Multi-Page Mode:
    • src/app/index.html
    • src/login/login.html
  Building in Lib Mode:
    • src/background/sw.js
    • src/content/content.js

[vite-plugin-web-extension] Building HTML Pages in Multi-Page Mode
transforming (416) src/app/components/EventsView/Timeline.js[BABEL] Note: The code generator has deoptimised the styling of $PROJECT_DIR/src/shared/metadata.js as it exceeds the max of 500KB.
transforming (4484) node_modules/htmlparser2/node_modules/dom-serializer/node_modUse of eval in "node_modules/store/plugins/lib/json2.js" is strongly discouraged as it poses security risks and may cause issues with minification.
✓ 4532 modules transformed.
Invalid substitution "$PROJECT_DIR/src/app/index" for placeholder "[name]" in "output.entryFileNames" pattern, can be neither absolute nor relative path.

Error

Invalid substitution "$PROJECT_DIR/src/app/index" for placeholder "[name]" in "output.entryFileNames" pattern, can be neither absolute nor relative path.

After that error is printed, the build process starts over again and loops forever until it runs out of heap space.

How can I resolve this error? Any guidance is greatly appreciated.


vite.config.ts

/* eslint-disable import/no-extraneous-dependencies */
import path from "node:path";
import webExtension from "vite-plugin-web-extension";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
  build: {
    outDir: path.resolve(__dirname, "dist"),
    emptyOutDir: true
  },
  plugins: [
    react({
      babel: {
        // babelrc: true
        plugins: [
          [
            "babel-plugin-jsx-pragmatic",
            { export: "jsx", module: "@emotion/core", import: "___EmotionJSX" }
          ],
          [
            "@babel/plugin-transform-react-jsx",
            { pragma: "___EmotionJSX", pragmaFrag: "React.Fragment" }
          ],
          ["emotion"]
        ]
      },
      jsxRuntime: "classic"
    }),
    webExtension({
      manifest: "manifest.json",
      assets: "icons",
      verbose: true,
      additionalInputs: [
        path.resolve(__dirname, "src/app/index.html"),
        path.resolve(__dirname, "src/login/login.html")
      ]
    })
  ],
  resolve: {
    alias: {
      "~": path.resolve(__dirname),
      src: path.resolve(__dirname, "src"),
      app: path.resolve(__dirname, "src/app"),
      shared: path.resolve(__dirname, "src/shared")
    }
  }
});
Project structure

.
├── README-FIREFOX.md
├── README.md
├── _locales
│   └── en
│       └── messages.json
├── extensionArchitecture.png
├── icons
│   ├── icon_128.png
│   ├── icon_16.png
│   └── icon_48.png
├── jest-puppeteer.config.js
├── jsconfig.json
├── karma.conf.js
├── license.txt
├── manifest.chrome.json
├── manifest.firefox.json
├── manifest.json
├── metadata.xlsx
├── node_modules/
├── package-lock.json
├── package.json
├── scripts/
├── src/
│   ├── app/
│   │   ├── App.js
│   │   ├── api/
│   │   ├── components/
│   │   ├── constants.js
│   │   ├── contexts/
│   │   ├── controllers/
│   │   ├── globalStyles.js
│   │   ├── hotReloadInDev.js
│   │   ├── images/
│   │   ├── index.html
│   │   ├── index.js
│   │   ├── networkDetection/
│   │   ├── state/
│   │   ├── staticCss/
│   │   ├── store.js
│   │   └── utils/
│   ├── background/
│   │   └── sw.js
│   ├── content/
│   │   ├── content.js
│   │   ├── embedCodeInjection.js
│   │   ├── injectedScripts/
│   │   ├── persistValidationToken.js
│   │   ├── scriptTagDetection.js
│   │   └── storage/
│   ├── login/
│   │   ├── LoginApp.js
│   │   ├── ims.js
│   │   ├── login.html
│   │   ├── loginPopup.js
│   │   └── loginStore.js
│   └── shared/
│       ├── appWindow.js
│       ├── browserApi
│       ├── constants.js
│       ├── errorReporter.js
│       ├── metadata.js
│       ├── queue.js
│       └── util
├── test.html
├── tests/
│   ├── configuration/
│   │   └── preprocess.js
│   ├── integration/
│   ├── secrets.js
│   ├── unit/
│   │   ├── app/
│   │   ├── content/
│   │   ├── helpers/
│   │   └── shared/
│   └── utils.js
└── vite.config.ts

3646 directories, 8907 files

aklinker1 commented 1 year ago

additionalInputs should be relative to the Vite root, not an absolute path. Try this instead:

https://v1.vite-plugin-web-extension.aklinker1.io/guide/configuration.html#additional-inputs

additionalInputs: ["src/app/index.html", "src/login/login.html"],

LMK if that doesn't work, I'll be able to look into this in a few hours when I get back home.

carterworks commented 1 year ago

Changing additionalInputs to a relative path fixed the error message about entry file names, but the infinite loop is still there for vite build (without --watch).

Any tips?

aklinker1 commented 1 year ago

I've seen the infinite loop before, it showed up while working on v2 of the extension. That was related to how plugins are managed in each build.

I haven't seen it happen in v1. Can you reproduce it in a minimal repo?

carterworks commented 1 year ago

I haven't seen it happen in v1. Can you reproduce it in a minimal repo?

Sure. Here is a minimal reproduction that loops on my machine.

https://github.com/carterworks/webext-vite-infinite-loop

Video of the loop:

https://user-images.githubusercontent.com/18412686/207716331-3e5eff2d-a0d7-4d91-8d5c-ebe52646a49d.mov

aklinker1 commented 1 year ago

I've figured out the issue and released an update, v1.4.7 that fixes the issue.

aklinker1 commented 1 year ago

@carterworks

carterworks commented 1 year ago

That works. You're the best. Thanks for the quick resolution.