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.
yarn add -D vite-plugin-public-path
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: [
// ...
]
});
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>
.
You can skip this plugin's processing of your index.html
(and, most likely, handle it yourself after this plugin) by:
false
: Disableindex.html
processing. This will cause the outputindex.html
contains the base placeholder, which lead to unusable HTML, which may help you processindex.html
yourself.- A
string
: if you pass a string, theconfig.base
placeholder will be replaced to this string in generatedindex.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.
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
.
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);
}
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__
})();
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);
}
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__
})();