vite-plugin-public-path
Version:
Vite's equivalent of `__webpack_public_path__` in Webpack. Works for `index.html` and modern/legacy build.
138 lines (102 loc) • 6.5 kB
Markdown
# vite-plugin-public-path
[](https://github.com/Menci/vite-plugin-public-path/actions?query=workflow%3ATest)
[](https://www.npmjs.com/package/vite-plugin-public-path)
[](http://commitizen.github.io/cz-cli/)
[](https://github.com/prettier/prettier)
[](LICENSE)
Vite's equivalent of [`__webpack_public_path__` in Webpack](https://webpack.js.org/guides/public-path/#on-the-fly). Works for `index.html` and modern/[legacy](https://www.npmjs.com/package/@vitejs/plugin-legacy) build.
You may need it if you want to load your resources from a CDN / multiple CDNs.
## Installation
```bash
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](https://www.npmjs.com/package/vite-plugin-html-minifier-terser).
```typescript
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.:
```typescript
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](https://developer.mozilla.org/en-US/docs/Glossary/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:
```javascript
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__"`:
```javascript
(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:
```javascript
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__"`:
```javascript
(function () {
function addScriptTag(attributes, inlineScriptCode) {
// code above
}
// __add_script_tags__
})();
```