Skip to content

Commit

Permalink
fix: support empty, relative and external base values
Browse files Browse the repository at this point in the history
close #1669
  • Loading branch information
yyx990803 committed Jan 23, 2021
1 parent 7306610 commit 00bc446
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 21 deletions.
8 changes: 7 additions & 1 deletion docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,13 @@ export default ({ command, mode }) => {
- **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.
Base public path when served in development or production. Valid values include:

- Absolute URL pathname, e.g. `/foo/`
- Full URL, e.g. `https://foo.com/`
- Empty string or `./` (for embedded deployment)

See [Public Base Path](/guide/build#public-base-path) for more details.

### mode

Expand Down
69 changes: 58 additions & 11 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import Rollup from 'rollup'
import { BuildOptions, resolveBuildOptions } from './build'
import { ServerOptions } from './server'
import { CSSOptions } from './plugins/css'
import { createDebugger, isObject, lookupFile, normalizePath } from './utils'
import {
createDebugger,
isExternalUrl,
isObject,
lookupFile,
normalizePath
} from './utils'
import { resolvePlugins } from './plugins'
import chalk from 'chalk'
import {
Expand All @@ -23,6 +29,7 @@ import { createLogger, Logger, LogLevel } from './logger'
import { DepOptimizationOptions } from './optimizer'
import { createFilter } from '@rollup/pluginutils'
import { ResolvedBuildOptions } from '.'
import { parse as parseUrl } from 'url'

const debug = createDebugger('vite:config')

Expand Down Expand Up @@ -238,16 +245,7 @@ export async function resolveConfig(
config.base = config.build.base
}

let BASE_URL = config.base || '/'
if (!BASE_URL.startsWith('/') || !BASE_URL.endsWith('/')) {
logger.warn(
chalk.bold.yellow(
`(!) "base" config option should start and end with "/".`
)
)
if (!BASE_URL.startsWith('/')) BASE_URL = '/' + BASE_URL
if (!BASE_URL.endsWith('/')) BASE_URL = BASE_URL + '/'
}
const BASE_URL = resolveBaseUrl(config.base, command === 'build', logger)

const resolvedBuildOptions = resolveBuildOptions(config.build)

Expand Down Expand Up @@ -339,6 +337,55 @@ export async function resolveConfig(
return resolved
}

/**
* Resolve base. Note that some users use Vite to build for non-web targets like
* electron or expects to deploy
*/
function resolveBaseUrl(
base: UserConfig['base'] = '/',
isBuild: boolean,
logger: Logger
): string {
// #1669 special treatment for empty for same dir relative base
if (base === '' || base === './') {
return isBuild ? base : '/'
}
if (base.startsWith('.')) {
logger.warn(
chalk.yellow.bold(
`(!) invalid "base" option: ${base}. The value can only be an absolute ` +
`URL, ./, or an empty string.`
)
)
base = '/'
}

// external URL
if (isExternalUrl(base)) {
if (!isBuild) {
// get base from full url during dev
const parsed = parseUrl(base)
base = parsed.pathname || '/'
}
} else {
// ensure leading slash
if (!base.startsWith('/')) {
logger.warn(
chalk.yellow.bold(`(!) "base" option should start with a slash.`)
)
base = '/' + base
}
}

// ensure ending slash
if (!base.endsWith('/')) {
logger.warn(chalk.yellow.bold(`(!) "base" option should end with a slash.`))
base += '/'
}

return base
}

export function mergeConfig(
a: Record<string, any>,
b: Record<string, any>,
Expand Down
38 changes: 29 additions & 9 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import postcssrc from 'postcss-load-config'
import merge from 'merge-source-map'
import {
NormalizedOutputOptions,
PluginContext,
RenderedChunk,
RollupError,
SourceMap
Expand Down Expand Up @@ -238,21 +239,13 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
return null
}

// replace asset url references with resolved url
chunkCSS = chunkCSS.replace(assetUrlRE, (_, fileId, postfix = '') => {
return config.base + this.getFileName(fileId) + postfix
})

if (config.build.cssCodeSplit) {
if (!code.trim()) {
// this is a shared CSS-only chunk that is empty.
emptyChunks.add(chunk.fileName)
}
// minify
if (config.build.minify) {
chunkCSS = await minifyCSS(chunkCSS, config)
}
if (opts.format === 'es') {
chunkCSS = await processChunkCSS(chunkCSS, config, this, false)
// emit corresponding css file
const fileHandle = this.emitFile({
name: chunk.name + '.css',
Expand All @@ -262,6 +255,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
chunkToEmittedCssFileMap.set(chunk, fileHandle)
} else if (!config.build.ssr) {
// legacy build, inline css
chunkCSS = await processChunkCSS(chunkCSS, config, this, true)
const style = `__vite_style__`
const injectCode =
`var ${style} = document.createElement('style');` +
Expand All @@ -284,6 +278,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
}
} else {
const extractedCss = outputToExtractedCSSMap.get(opts) || ''
chunkCSS = await processChunkCSS(chunkCSS, config, this, false)
outputToExtractedCSSMap.set(opts, extractedCss + chunkCSS)
return null
}
Expand Down Expand Up @@ -739,6 +734,31 @@ function rewriteCssUrls(
})
}

async function processChunkCSS(
css: string,
config: ResolvedConfig,
pluginCtx: PluginContext,
isInlined: boolean
): Promise<string> {
// replace asset url references with resolved url.
const isRelativeBase = config.base === '' || config.base.startsWith('.')
css = css.replace(assetUrlRE, (_, fileId, postfix = '') => {
const filename = pluginCtx.getFileName(fileId) + postfix
if (!isRelativeBase || isInlined) {
// absoulte base or relative base but inlined (injected as style tag into
// index.html) use the base as-is
return config.base + filename
} else {
// relative base + extracted CSS - asset file will be in the same dir
return `./${path.posix.basename(filename)}`
}
})
if (config.build.minify) {
css = await minifyCSS(css, config)
}
return css
}

let CleanCSS: any

async function minifyCSS(css: string, config: ResolvedConfig) {
Expand Down

0 comments on commit 00bc446

Please sign in to comment.