Skip to content

Vite's equivalent of `__webpack_public_path__` in Webpack. Works for `index.html` and modern/legacy build.

License

Notifications You must be signed in to change notification settings

Menci/vite-plugin-public-path

Repository files navigation

vite-plugin-public-path

Test Status npm Commitizen friendly code style: prettier License

Vite's equivalent of __webpack_public_path__ in Webpack. Works for index.html and modern/legacy build.

You may need it if you want to load your resources from a CDN / multiple CDNs.

Installation

yarn add -D vite-plugin-public-path

Basic Usage

Put this plugin in your plugin list. It should be put after almost all plugins, expect for resource minimizers, e.g. you may need vite-plugin-html-minifier-terser.

import react from "@nestjs/plugin-react";
import legacy from "@nestjs/plugin-legacy";
import publicPath from "vite-plugin-public-path";
import minifyHtml from "vite-plugin-html-minifier-terser";

export default defineConfig({
  plugins: [
    react(),
    legacy(),
    publicPath({
      // A JS expression evaluates on client side each time when loading a new file
      // Should evaluate to a string ending with "/"
      publicPathExpression: "window.publicPath",
      // See below for explanation of `options.html`
      html: true,
      // (Optional) The plugin will not rewrite any <script> tags whose src matches the provided filters
      // Useful for your external dependencies
      // Can be string, string[], RegExp or RegExp[]
      excludeScripts: /^https:.*systemjs/
    }),
    // You may need `vite-plugin-html-minifier-terser` since this plugin outputs non-minified inline JS code
    minifyHtml({ minifyJS: true })
  ]
});

Use a unique placeholder for config.base when building but NOT previewing. The placeholder value will be replaced to dynamic public path expression, so make sure it doesn't occur in your application code or assets' contents. e.g.:

export default defineConfig({
  base: process.env.NODE_ENV === "production" ? "/__vite_base__/" : "/",
  plugins: [
    // ...
  ]
});

HTML Substitution

To make sure the initial scripts and assets in the HTML file load from your dynamic public path, we transform <link> and <script> tags in index.html to a piece of inline JS code, which creates and appends that tags dynamically.

You should initialize this expression's value (i.e. assign to it if it's a global variable or declare the function if it's calling one) in a <script> tag in <head>. We will start creating <link> tags after the last <script> tag in your <head>.

Skip HTML Substitution

You can skip this plugin's processing of your index.html (and, most likely, handle it yourself after this plugin) by:

  • false: Disable index.html processing. This will cause the output index.html contains the base placeholder, which lead to unusable HTML, which may help you process index.html yourself.
  • A string: if you pass a string, the config.base placeholder will be replaced to this string in generated index.html. This just removes the impact of placeholder.
    • NOTE: If you (unlikely) just use this option and do no more processing, for modern build, this doesn't match Webpack's behavior "load initial JS/CSS files from original host but imported from dynamic public path", because ES module imports generated by Vite use ALL relative URLs. For legacy build it matches that behavior.

Advanced Options

There're some advanced options for HTML substitution. For some reason, if you want to customize the method of dynamically creating and appending tags, you can pass a HtmlAdvancedOptions to options.html.

You will need to implement two functions addLinkTag and addScriptTag. And two placeholders in contexts with access to those two functions (to allow minifier shortening the names, put them in a IIFE). All <link> and <script> tags will be transformed to calls to those two functions.

If you are confused, just refer to the dist/index.html generated with simple html: true.

functionNameAddLinkTag

The function name to add <link> tag, e.g. "addLinkTag". The function would be like:

function addLinkTag(rel, href) {
  var link = document.createElement("link");
  link.rel = rel;
  link.href = href;
  document.head.appendChild(link);
}

addLinkTagsPlaceholder

This string in your HTML file (should be in a <script> in <head>) will be replaced to functionNameAddLinkTag expressions. Use a comment to prevent syntax errors on previewing (this plugin does only apply to building, not previewing). For example "// __add_link_tags__":

(function () {
  function addLinkTag(rel, href) {
    // code above
  }

  // __add_link_tags__
})();

functionNameAddScriptTag

The function name to add <script> tag, e.g. "addScriptTag". The function would be like:

function addScriptTag(attributes, inlineScriptCode) {
  var script = document.createElement("script");
  if (attributes) for (var key in attributes) script.setAttribute(key, attributes[key]);
  // This is required to make them execute in-order
  script.async = false;
  if (inlineScriptCode) script.src = "data:text/javascript," + inlineScriptCode;
  document.body.appendChild(script);
}

addScriptTagsPlaceholder

This string in your HTML file (should be in a <script> in <body>) will be replaced to functionNameAddScriptTag expressions. Use a comment to prevent syntax errors on previewing (this plugin does only apply to building, not previewing). For example "// __add_script_tags__":

(function () {
  function addScriptTag(attributes, inlineScriptCode) {
    // code above
  }

  // __add_script_tags__
})();

About

Vite's equivalent of `__webpack_public_path__` in Webpack. Works for `index.html` and modern/legacy build.

Resources

License

Stars

Watchers

Forks

Packages

No packages published