提交 6ed60fcb 编写于 作者: E Evan You

handle base during dev

上级 6f7bff63
......@@ -9,10 +9,10 @@ module.exports = {
dest: 'vuepress',
base,
head: [
['link', { rel: 'icon', href: `${base}logo.png` }]
['link', { rel: 'icon', href: `/logo.png` }]
],
themeConfig: {
logo: `${base}logo.png`,
logo: `/logo.png`,
repo: 'vuejs/vuepress',
docsDir: 'docs',
nav: [
......
......@@ -20,7 +20,7 @@
### themeConfig
Also see [config options for the default theme](./default-theme.md).
Also see [config options for the default theme](../guide/default-theme.md).
## Markdown
......
......@@ -17,12 +17,16 @@ This would work the same way as if you are referencing it inside a `*.vue` file
## Public Files
Sometimes you may need to provide some static assets that are not directly referenced in any of your markdown or theme components - for example, favicons and PWA icons. In that case you can put them inside `.vuepress/public` and they will be copied to the root of the generated static build.
Sometimes you may need to provide some static assets that are not directly referenced in any of your markdown or theme components - for example, favicons and PWA icons. In such cases you can put them inside `.vuepress/public` and they will be copied to the root of the generated directory.
## Referencing Base URL Dynamically
## Base URL
If your site is deployed to a non-root URL, you will need to set the `base` option in `.vuepress/config.js`. The value of this option will be available anywhere in markdown or your components as `$site.base`. In order to use it though, you will have to use direct HTML along with Vue bindings:
If your site is deployed to a non-root URL, you will need to set the `base` option in `.vuepress/config.js`. For example, if you plan to deploy your site to `https://foo.github.io/bar/`, then `base` should be set to `"/bar/"` (it should always start and end with a slash).
With a base URL, if you want to reference an image in `.vuepress/public`, you'd have to use URLs like `/bar/image.png`. However, this is brittle if you ever decide to change the `base` later. To help with that, VuePress provides a built-in helper `$withBase` (injected onto Vue's prototype) that generates the correct path:
``` md
<img :src="$site.base + 'foo.png'" alt="foo">
<img :src="$withBase('/foo.png')" alt="foo">
```
In addition, if a `base` is set, all asset URLs in `.vuepress/config.js` will get the base automatically prepended as well.
......@@ -6,6 +6,19 @@ import metadataMixin from './metadataMixin'
import { routes } from './.temp/routes'
import { siteData } from './.temp/siteData'
// suggest dev server restart on base change
if (module.hot) {
const prevBase = siteData.base
module.hot.accept('./.temp/siteData', () => {
if (siteData.base !== prevBase) {
window.alert(
`[vuepress] Site base has changed. ` +
`Please restart dev server to ensure correct paths.`
)
}
})
}
Vue.use(Router)
// mixin for exposing $site and $page
......@@ -14,6 +27,16 @@ Vue.mixin(metadataMixin)
// component for rendering markdown content and setting title etc.
Vue.component('Content', Content)
// global helper for adding base path to absolute urls
Vue.prototype.$withBase = function (path) {
const base = this.$site.base
if (path.charAt(0) === '/') {
return base + path.slice(1)
} else {
return path
}
}
// add 404 route
routes.push({
path: '*',
......
import { siteData } from './.temp/siteData'
import { findPageForPath } from './util'
if (module.hot) {
module.hot.accept('./.temp/siteData', () => {
const { siteData } = require('./.temp/siteData')
console.log(`reload from mixin: ` + siteData)
})
}
siteData.pages.forEach(page => {
if (!page.frontmatter) {
page.frontmatter = {}
......@@ -13,7 +20,10 @@ export default {
return siteData
},
$page () {
return findPageForPath(this.$route.path)
return findPageForPath(
this.$site.pages,
this.$route.path
)
}
}
}
import { siteData } from './.temp/siteData'
export function pathToComponentName (path) {
if (path.charAt(path.length - 1) === '/') {
return `page${path.replace(/\//g, '-') + 'index'}`
......@@ -8,8 +6,7 @@ export function pathToComponentName (path) {
}
}
export function findPageForPath (path) {
const pages = siteData.pages
export function findPageForPath (pages, path) {
for (let i = 0; i < pages.length; i++) {
const page = pages[i]
if (page.path === path) {
......@@ -18,7 +15,7 @@ export function findPageForPath (path) {
}
}
export function getTitle (page) {
export function getTitle (siteData, page) {
const selfTitle = page.frontmatter.home ? null : (
page.frontmatter.title || // explicit title
page.title // inferred title
......
<template>
<div class="home">
<div class="hero">
<img v-if="data.heroImage" :src="data.heroImage">
<img v-if="data.heroImage" :src="$withBase(data.heroImage)">
<h1>{{ data.heroText || $site.title }}</h1>
<p class="description">
{{ data.tagline || $site.description }}
......
......@@ -35,7 +35,7 @@ export default {
created () {
if (this.$ssrContext) {
this.$ssrContext.title = getTitle(this.$page)
this.$ssrContext.title = getTitle(this.$site, this.$page)
this.$ssrContext.lang = getLang(this.$page)
}
},
......@@ -44,7 +44,7 @@ export default {
// update title / meta tags
this.currentMetaTags = []
const updateMeta = () => {
document.title = getTitle(this.$page)
document.title = getTitle(this.$site, this.$page)
document.documentElement.lang = getLang(this.$page)
this.currentMetaTags = updateMetaTags(this.$page, this.currentMetaTags)
}
......
......@@ -4,7 +4,7 @@
<router-link to="/">
<img class="logo"
v-if="$site.themeConfig.logo"
:src="$site.themeConfig.logo">
:src="$withBase($site.themeConfig.logo)">
<span class="site-name"
v-if="$site.title"
:class="{ 'can-hide': $site.themeConfig.logo }">
......
......@@ -6,6 +6,7 @@ module.exports = async function dev (sourceDir, cliOptions = {}) {
const chokidar = require('chokidar')
const serve = require('webpack-serve')
const convert = require('koa-connect')
const mount = require('koa-mount')
const serveStatic = require('koa-static')
const HTMLPlugin = require('html-webpack-plugin')
const history = require('connect-history-api-fallback')
......@@ -50,13 +51,15 @@ module.exports = async function dev (sourceDir, cliOptions = {}) {
config
.plugin('html')
.use(HTMLPlugin, [
{ template: path.resolve(__dirname, 'app/index.dev.html') }
])
.use(HTMLPlugin, [{
template: path.resolve(__dirname, 'app/index.dev.html')
}])
config
.plugin('site-data')
.use(HeadPlugin, [options.siteConfig.head || []])
.use(HeadPlugin, [{
tags: options.siteConfig.head || []
}])
config = config.toConfig()
const userConfig = options.siteConfig.configureWebpack
......@@ -73,7 +76,7 @@ module.exports = async function dev (sourceDir, cliOptions = {}) {
isFirst = false
console.log(
`\n VuePress dev server listening at ${
chalk.cyan(`http://localhost:${port}`)
chalk.cyan(`http://localhost:${port}${options.publicPath}`)
}\n`
)
} else {
......@@ -91,8 +94,9 @@ module.exports = async function dev (sourceDir, cliOptions = {}) {
port,
add: app => {
const userPublic = path.resolve(sourceDir, '.vuepress/public')
// respect base when serving static files...
if (fs.existsSync(userPublic)) {
app.use(serveStatic(userPublic))
app.use(mount(options.publicPath, serveStatic(userPublic)))
}
app.use(convert(history({
......
......@@ -61,13 +61,31 @@ async function resolveOptions (sourceDir) {
])
}
// normalize head tag urls for base
const base = siteConfig.base || '/'
if (base !== '/' && siteConfig.head) {
siteConfig.head.forEach(tag => {
const attrs = tag[1]
if (attrs) {
for (const name in attrs) {
if (name === 'src' || name === 'href') {
const value = attrs[name]
if (value.charAt(0) === '/') {
attrs[name] = base + value.slice(1)
}
}
}
}
})
}
const options = {
siteConfig,
sourceDir,
outDir: siteConfig.dest
? path.resolve(siteConfig.dest)
: path.resolve(sourceDir, '.vuepress/dist'),
publicPath: siteConfig.base || '/',
publicPath: base,
pageFiles: sort(await globby(['**/*.md', '!.vuepress'], { cwd: sourceDir })),
pagesData: null,
themePath: null,
......
const { normalizeHeadTag } = require('../util')
module.exports = class SiteDataPlugin {
constructor (tags = []) {
constructor ({ tags }) {
this.tags = tags
}
......
......@@ -1246,7 +1246,7 @@ debug@*, debug@^3.1.0:
dependencies:
ms "2.0.0"
debug@^2.2.0, debug@^2.3.3, debug@^2.6.3, debug@^2.6.8:
debug@^2.2.0, debug@^2.3.3, debug@^2.6.1, debug@^2.6.3, debug@^2.6.8:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
......@@ -3079,7 +3079,7 @@ kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
koa-compose@^3.0.0:
koa-compose@^3.0.0, koa-compose@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7"
dependencies:
......@@ -3104,6 +3104,13 @@ koa-is-json@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14"
koa-mount@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/koa-mount/-/koa-mount-3.0.0.tgz#08cab3b83d31442ed8b7e75c54b1abeb922ec197"
dependencies:
debug "^2.6.1"
koa-compose "^3.2.1"
koa-send@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-4.1.3.tgz#0822207bbf5253a414c8f1765ebc29fa41353cb6"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册