Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support base option during dev #1556

Merged
merged 20 commits into from
Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ export default ({ command, mode }) => {

See [Project Root](/guide/#project-root) for more details.

### base

- **Type:** `string`
- **Default:** `/`

Base public path when served in development or production. Note the path should start and end with `/`. See [Public Base Path](/guide/build#public-base-path) for more details.

### mode

- **Type:** `string`
Expand Down Expand Up @@ -322,13 +329,6 @@ export default ({ command, mode }) => {

## Build Options

### build.base

- **Type:** `string`
- **Default:** `/`

Base public path when served in production. Note the path should start and end with `/`. See [Public Base Path](/guide/build#public-base-path) for more details.

### build.target

- **Type:** `string`
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Legacy browsers can be supported via [@vitejs/plugin-legacy](https://github.com/

- Related: [Asset Handling](./features#asset-handling)

If you are deploying your project under a nested public path, simply specify the [`build.base` config option](/config/#build-base) and all asset paths will be rewritten accordingly. This option can also be specified as a command line flag, e.g. `vite build --base=/my/public/path/`.
If you are deploying your project under a nested public path, simply specify the [`base` config option](/config/#base) and all asset paths will be rewritten accordingly. This option can also be specified as a command line flag, e.g. `vite build --base=/my/public/path/`.

JS-imported asset URLs, CSS `url()` references, and asset references in your `.html` files are all automatically adjusted to respect this option during build.

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/env-and-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Vite exposes env variables on the special **`import.meta.env`** object. Some bui

- **`import.meta.env.MODE`**: {string} the [mode](#modes) the app is running in.

- **`import.meta.env.BASE_URL`**: {string} the base url the app is being served from. In development, this is always `/`. In production, this is determined by the [`build.base` config option](/config/#build-base).
- **`import.meta.env.BASE_URL`**: {string} the base url the app is being served from. This is determined by the [`base` config option](/config/#base).

- **`import.meta.env.PROD`**: {boolean} whether the app is running in production.

Expand Down
30 changes: 27 additions & 3 deletions packages/playground/assets/__tests__/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,40 @@ import {

const assetMatch = isBuild
? /\/foo\/assets\/asset\.\w{8}\.png/
: '/nested/asset.png'
: '/foo/nested/asset.png'

const iconMatch = isBuild ? `/foo/icon.png` : `icon.png`
const iconMatch = `/foo/icon.png`

test('should have no 404s', () => {
browserLogs.forEach((msg) => {
expect(msg).not.toMatch('404')
})
})

describe('injected scripts', () => {
test('@vite/client', async () => {
const hasClient = await page.$(
'script[type="module"][src="/foo/@vite/client"]'
)
if (isBuild) {
expect(hasClient).toBeFalsy()
} else {
expect(hasClient).toBeTruthy()
}
})

test('html-proxy', async () => {
const hasHtmlProxy = await page.$(
'script[type="module"][src="/foo/index.html?html-proxy&index=0.js"]'
)
if (isBuild) {
expect(hasHtmlProxy).toBeFalsy()
} else {
expect(hasHtmlProxy).toBeTruthy()
}
})
})

describe('raw references from /public', () => {
test('load raw js from /public', async () => {
expect(await page.textContent('.raw-js')).toMatch('[success]')
Expand Down Expand Up @@ -70,7 +94,7 @@ describe('css url() references', () => {
})

test('base64 inline', async () => {
const match = isBuild ? `data:image/png;base64` : `/icon.png`
const match = isBuild ? `data:image/png;base64` : `/foo/nested/icon.png`
expect(await getBg('.css-url-base64-inline')).toMatch(match)
expect(await getBg('.css-url-quotes-base64-inline')).toMatch(match)
})
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/assets/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* @type {import('vite').UserConfig}
*/
module.exports = {
base: '/foo/',
build: {
base: '/foo/',
outDir: 'dist/foo'
}
}
6 changes: 3 additions & 3 deletions packages/plugin-legacy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ function viteLegacyPlugin(options = {}) {
tag: 'script',
attrs: {
type: 'module',
src: `${config.build.base}${modernPolyfillFilename}`
src: `${config.base}${modernPolyfillFilename}`
}
})
} else if (modernPolyfills.size) {
Expand Down Expand Up @@ -295,7 +295,7 @@ function viteLegacyPlugin(options = {}) {
tag: 'script',
attrs: {
nomodule: true,
src: `${config.build.base}${legacyPolyfillFilename}`
src: `${config.base}${legacyPolyfillFilename}`
},
injectTo: 'body'
})
Expand All @@ -318,7 +318,7 @@ function viteLegacyPlugin(options = {}) {
// script content will stay consistent - which allows using a constant
// hash value for CSP.
id: legacyEntryId,
'data-src': config.build.base + legacyEntryFilename
'data-src': config.base + legacyEntryFilename
},
children: systemJSInlineCode,
injectTo: 'body'
Expand Down
4 changes: 3 additions & 1 deletion packages/plugin-vue/src/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ export function resolveTemplateCompilerOptions(
// request
if (filename.startsWith(options.root)) {
assetUrlOptions = {
base: '/' + slash(path.relative(options.root, path.dirname(filename)))
base:
options.devServer.config.base +
slash(path.relative(options.root, path.dirname(filename)))
}
}
} else {
Expand Down
11 changes: 9 additions & 2 deletions packages/vite/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ErrorOverlay, overlayId } from './overlay'

// injected by the hmr plugin when served
declare const __ROOT__: string
declare const __BASE__: string
declare const __MODE__: string
declare const __DEFINES__: Record<string, any>
declare const __HMR_PROTOCOL__: string
Expand Down Expand Up @@ -38,6 +39,8 @@ const socketProtocol =
__HMR_PROTOCOL__ || (location.protocol === 'https:' ? 'wss' : 'ws')
const socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`
const socket = new WebSocket(`${socketProtocol}://${socketHost}`, 'vite-hmr')
const base = __BASE__ || '/'
const baseNoSlash = base.replace(/\/$/, '')

function warnFailedFetch(err: Error, path: string | string[]) {
if (!err.message.match('fetch')) {
Expand Down Expand Up @@ -107,9 +110,10 @@ async function handleMessage(payload: HMRPayload) {
// if html file is edited, only reload the page if the browser is
// currently on that page.
const pagePath = location.pathname
const payloadPath = baseNoSlash + payload.path
if (
pagePath === payload.path ||
(pagePath.endsWith('/') && pagePath + 'index.html' === payload.path)
pagePath === payloadPath ||
(pagePath.endsWith('/') && pagePath + 'index.html' === payloadPath)
) {
location.reload()
}
Expand Down Expand Up @@ -259,6 +263,9 @@ export function removeStyle(id: string) {
}

async function fetchUpdate({ path, acceptedPath, timestamp }: Update) {
path = baseNoSlash + path
acceptedPath = baseNoSlash + acceptedPath

const mod = hotModulesMap.get(path)
if (!mod) {
// In a code-splitting project,
Expand Down
14 changes: 5 additions & 9 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { ssrManifestPlugin } from './ssr/ssrManifestPlugin'
export interface BuildOptions {
/**
* Base public path when served in production.
* @default '/'
* @deprecated `base` is now a root-level config option.
*/
base?: string
/**
Expand Down Expand Up @@ -168,11 +168,10 @@ export interface LibraryOptions {

export type LibraryFormats = 'es' | 'cjs' | 'umd' | 'iife'

export function resolveBuildOptions(
raw?: BuildOptions
): Required<BuildOptions> {
const resolved: Required<BuildOptions> = {
base: '/',
export type ResolvedBuildOptions = Required<Omit<BuildOptions, 'base'>>

export function resolveBuildOptions(raw?: BuildOptions): ResolvedBuildOptions {
const resolved: ResolvedBuildOptions = {
target: 'modules',
polyfillDynamicImport: raw?.target !== 'esnext' && !raw?.lib,
outDir: 'dist',
Expand Down Expand Up @@ -207,9 +206,6 @@ export function resolveBuildOptions(
resolved.target = 'es2019'
}

// ensure base ending slash
resolved.base = resolved.base.replace(/([^/])$/, '$1/')

// normalize false string into actual false
if ((resolved.minify as any) === 'false') {
resolved.minify = false
Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface GlobalCLIOptions {
config?: string
c?: boolean | string
root?: string
base?: string
r?: string
mode?: string
m?: string
Expand All @@ -38,6 +39,7 @@ function cleanOptions(options: GlobalCLIOptions) {
delete ret.config
delete ret.c
delete ret.root
delete ret.base
delete ret.r
delete ret.mode
delete ret.m
Expand All @@ -50,6 +52,7 @@ function cleanOptions(options: GlobalCLIOptions) {
cli
.option('-c, --config <file>', `[string] use specified config file`)
.option('-r, --root <path>', `[string] use specified root directory`)
.option('--base <path>', `[string] public base path (default: /)`)
.option('-l, --logLevel <level>', `[string] silent | error | warn | all`)
.option('--clearScreen', `[boolean] allow/disable clear screen when logging`)
.option('-d, --debug [feat]', `[string | boolean] show debug logs`)
Expand Down Expand Up @@ -77,6 +80,7 @@ cli
try {
const server = await createServer({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
Expand All @@ -95,7 +99,6 @@ cli
// build
cli
.command('build [root]')
.option('--base <path>', `[string] public base path (default: /)`)
.option('--target <target>', `[string] transpile target (default: 'modules')`)
.option('--outDir <dir>', `[string] output directory (default: dist)`)
.option(
Expand Down Expand Up @@ -141,6 +144,7 @@ cli
try {
await build({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
Expand Down Expand Up @@ -169,6 +173,7 @@ cli
const config = await resolveConfig(
{
root,
base: options.base,
configFile: options.config,
logLevel: options.logLevel
},
Expand Down
Loading