An open API service indexing awesome lists of open source software.

https://github.com/menci/vite-plugin-public-path

Vite's equivalent of `__webpack_public_path__` in Webpack. Works for `index.html` and modern/legacy build.
https://github.com/menci/vite-plugin-public-path

Last synced: about 1 year ago
JSON representation

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

Awesome Lists containing this project

README

          

# vite-plugin-public-path

[![Test Status](https://img.shields.io/github/workflow/status/Menci/vite-plugin-public-path/Test?style=flat-square)](https://github.com/Menci/vite-plugin-public-path/actions?query=workflow%3ATest)
[![npm](https://img.shields.io/npm/v/vite-plugin-public-path?style=flat-square)](https://www.npmjs.com/package/vite-plugin-public-path)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square)](http://commitizen.github.io/cz-cli/)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
[![License](https://img.shields.io/github/license/Menci/vite-plugin-public-path?style=flat-square)](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 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__
})();
```