UNPKG

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
# 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 <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__ })(); ```