Skip to content

Commit ef9715f

Browse files
committed
tweaks
1 parent ad4aef0 commit ef9715f

14 files changed

+104
-64
lines changed

Diff for: bin/vuepress.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
const path = require('path')
22
const chalk = require('chalk')
3-
const { serve, build } = require('../lib')
3+
const { dev, build } = require('../lib')
44

55
const sourceDir = path.resolve(process.cwd(), 'docs')
66

77
const command = process.argv.slice(2)[0]
88

9-
if (command === 'build') {
10-
wrapCommand(build)(sourceDir)
9+
if (command === 'dev') {
10+
wrapCommand(dev)(sourceDir)
1111
}
1212

13-
if (command === 'serve') {
14-
wrapCommand(serve)(sourceDir)
13+
if (command === 'build') {
14+
wrapCommand(build)(sourceDir)
1515
}
1616

1717
function wrapCommand (fn) {

Diff for: docs/recipes.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Recipes

Diff for: lib/app/app.js

+26-17
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,43 @@
11
import Vue from 'vue'
22
import Router from 'vue-router'
3-
Vue.use(Router)
4-
5-
// register-commponents.js registers all *.vue files found in _components
6-
// as global async components
7-
import './.temp/register-components'
3+
import Content from './Content'
4+
import NotFound from '~notFound'
5+
6+
// .temp/siteData.js is a dynamically generated file that:
7+
// 1. registers all *.md pages and *.vue files found in _components as global
8+
// async components;
9+
// 2. exports siteData
10+
// 3. exports routes
11+
import { siteData, routes } from './.temp/siteData'
12+
13+
routes.push({
14+
path: '*',
15+
component: NotFound
16+
})
817

9-
// routes are generated from md files
10-
import routes from './.temp/routes'
18+
Vue.use(Router)
1119

12-
// expose Vue Press data
13-
const inBrowser = typeof window !== 'undefined'
20+
// component for rendering markdown content and setting title etc.
21+
Vue.component('Content', Content)
1422

1523
Vue.mixin({
1624
computed: {
1725
$site () {
18-
return inBrowser ? window.VUEPRESS_DATA : this.$ssrContext.siteData
26+
return siteData
1927
},
2028
$page () {
21-
const page = this.$site.pages[this.$route.path]
22-
page.frontmatter = page.frontmatter || {}
23-
return page
29+
const pages = siteData.pages
30+
for (let i = 0; i < pages.length; i++) {
31+
const page = pages[i]
32+
if (page.path === this.$route.path) {
33+
page.frontmatter = page.frontmatter || {}
34+
return page
35+
}
36+
}
2437
}
2538
}
2639
})
2740

28-
// component for rendering markdown content and setting title etc.
29-
import Content from './Content'
30-
Vue.component('Content', Content)
31-
3241
export function createApp () {
3342
const router = new Router({
3443
mode: 'history',

Diff for: lib/app/index.ssr.html

-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
{{{ userHeadTags }}}
66
{{{ renderResourceHints() }}}
77
{{{ renderStyles() }}}
8-
<script>
9-
window.VUEPRESS_DATA = {{{ JSON.stringify(siteData) }}}
10-
</script>
118
</head>
129
<body>
1310
<!--vue-ssr-outlet-->

Diff for: lib/build.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,22 @@ module.exports = async function build (sourceDir) {
4444
.map(renderHeadTag)
4545
.join('\n ')
4646

47-
await Promise.all(Object.keys(options.siteData.pages).map(async (url) => {
47+
await Promise.all(options.siteData.pages.map(async (page) => {
4848
const context = {
49-
url,
49+
url: page.path,
5050
userHeadTags,
51-
siteData: options.siteData,
5251
title: 'VuePress',
5352
lang: 'en'
5453
}
5554

56-
const html = await renderer.renderToString(context)
57-
58-
const page = options.siteData.pages[url]
55+
let html
56+
try {
57+
html = await renderer.renderToString(context)
58+
} catch (e) {
59+
console.error(chalk.red(`Error rendering ${page.path}:`))
60+
console.error(e.stack)
61+
return
62+
}
5963
const filename = page.path === '/' ? 'index.html' : page.path.replace(/^\//, '')
6064
const filePath = path.resolve(targetDir, filename)
6165
await mkdirp(path.dirname(filePath))
@@ -69,10 +73,10 @@ module.exports = async function build (sourceDir) {
6973
return reject(err)
7074
}
7175
if (stats.hasErrors()) {
72-
reject(`Failed to compile with errors.`)
7376
stats.toJson().errors.forEach(err => {
7477
console.error(err)
7578
})
79+
reject(new Error(`Failed to compile with errors.`))
7680
return
7781
}
7882
resolve()
File renamed without changes.

Diff for: lib/default-theme/NotFound.vue

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<h1>404</h1>
3+
</template>

Diff for: lib/serve.js renamed to lib/dev.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
module.exports = async function serve (sourceDir) {
1+
module.exports = async function dev (sourceDir) {
22
const path = require('path')
33
const chalk = require('chalk')
4-
const prepare = require('./prepare')
4+
const chokidar = require('chokidar')
55
const webpack = require('webpack')
66
const serve = require('webpack-serve')
77
const HTMLPlugin = require('html-webpack-plugin')
88
const convert = require('koa-connect')
99
const history = require('connect-history-api-fallback')
1010
const createClientConfig = require('./webpack/clientConfig')
11-
const SiteDataPlugin = require('./webpack/SiteDataPlugin')
11+
const HeadPlugin = require('./webpack/HeadPlugin')
12+
const prepare = require('./prepare')
1213

1314
const options = await prepare(sourceDir)
1415

16+
// setup watchers to update options and dynamically generated files
17+
const pagesWatcher = chokidar.watch([
18+
path.join(sourceDir, '**/*.md'),
19+
path.join(sourceDir, '_components/**/*.vue')
20+
], {
21+
ignoreInitial: true
22+
})
23+
pagesWatcher.on('add', () => prepare(sourceDir))
24+
pagesWatcher.on('unlink', () => prepare(sourceDir))
25+
26+
// resolve webpack config
1527
const _config = createClientConfig(options)
1628

1729
_config
@@ -22,7 +34,7 @@ module.exports = async function serve (sourceDir) {
2234

2335
_config
2436
.plugin('site-data')
25-
.use(SiteDataPlugin, [options.siteData, options.siteConfig.head])
37+
.use(HeadPlugin, [options.siteConfig.head || []])
2638

2739
const config = _config.toConfig()
2840
const compiler = webpack(config)

Diff for: lib/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1+
exports.dev = require('./dev')
12
exports.build = require('./build')
2-
exports.serve = require('./serve')

Diff for: lib/prepare.js

+31-14
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,22 @@ module.exports = async function prepare (sourceDir) {
99
const options = await resolveOptions(sourceDir)
1010

1111
// 2. generate dynamic component registration file
12-
await genComponentRegistrationFile(options)
12+
const componentCode = await genComponentRegistrationFile(options)
1313

1414
// 3. generate routes
15-
await genRoutesFile(options)
15+
const routesCode = await genRoutesFile(options)
16+
17+
// 4. generate siteData
18+
const dataCode = `export const siteData = ${JSON.stringify(options.siteData, null, 2)}`
19+
20+
fs.writeFileSync(
21+
path.join(tempPath, 'siteData.js'),
22+
[
23+
componentCode,
24+
routesCode,
25+
dataCode
26+
].join('\n\n')
27+
)
1628

1729
return options
1830
}
@@ -25,29 +37,35 @@ async function resolveOptions (sourceDir) {
2537
siteConfig,
2638
sourceDir,
2739
publicPath: siteConfig.baseUrl || '/',
28-
themePath: path.resolve(__dirname, 'default-theme/App.vue'),
40+
themePath: path.resolve(__dirname, 'default-theme/Layout.vue'),
41+
notFoundPath: path.resolve(__dirname, 'default-theme/NotFound.vue'),
2942
pages: await globby(['**/*.md'], { cwd: sourceDir })
3043
}
3144

3245
// resolve theme
33-
const themePath = path.resolve(sourceDir, '_theme/App.vue')
46+
const themePath = path.resolve(sourceDir, '_theme/Layout.vue')
3447
if (fs.existsSync(themePath)) {
3548
options.themePath = themePath
3649
}
3750

38-
const pagesData = {}
39-
options.pages.forEach(file => {
51+
const notFoundPath = path.resolve(sourceDir, '_theme/NotFound.vue')
52+
if (fs.existsSync(notFoundPath)) {
53+
options.notFoundPath = notFoundPath
54+
}
55+
56+
const pagesData = options.pages.map(file => {
4057
const name = file.replace(/\.md$/, '').replace(/\\/g, '/')
4158
const urlPath = '/' + (name === 'index' ? '' : (name + '.html'))
4259
const content = fs.readFileSync(path.resolve(sourceDir, file), 'utf-8')
43-
const data = pagesData[urlPath] = {
60+
const data = {
4461
path: urlPath
4562
}
4663
const frontmatter = yaml.loadFront(content)
4764
delete frontmatter.__content
4865
if (Object.keys(frontmatter).length) {
4966
data.frontmatter = frontmatter
5067
}
68+
return data
5169
})
5270

5371
options.siteData = Object.assign({}, siteConfig.data, {
@@ -70,8 +88,7 @@ async function genComponentRegistrationFile ({ sourceDir, pages }) {
7088

7189
const components = (await resolveComponents(sourceDir)) || []
7290
const all = [...pages, ...components]
73-
const file = `import Vue from 'vue'\n` + all.map(genImport).join('\n')
74-
fs.writeFileSync(path.join(tempPath, 'register-components.js'), file)
91+
return `import Vue from 'vue'\n` + all.map(genImport).join('\n')
7592
}
7693

7794
function toComponentName (file) {
@@ -89,11 +106,11 @@ async function resolveComponents (sourceDir) {
89106
if (!fs.existsSync(componentDir)) {
90107
return
91108
}
92-
return await globby(['*.vue'], { cwd: componentDir })
109+
return await globby(['**/*.vue'], { cwd: componentDir })
93110
}
94111

95112
async function genRoutesFile ({ sourceDir, siteData: { pages }}) {
96-
function genRoute (path) {
113+
function genRoute ({ path }) {
97114
const code = `
98115
{
99116
path: ${JSON.stringify(path)},
@@ -102,8 +119,8 @@ async function genRoutesFile ({ sourceDir, siteData: { pages }}) {
102119
return code
103120
}
104121

105-
const file =
122+
return (
106123
`import Theme from '~theme'\n` +
107-
`export default [${Object.keys(pages).map(genRoute).join(',')}\n]`
108-
fs.writeFileSync(path.join(tempPath, 'routes.js'), file)
124+
`export const routes = [${pages.map(genRoute).join(',')}\n]`
125+
)
109126
}

Diff for: lib/webpack/SiteDataPlugin.js renamed to lib/webpack/HeadPlugin.js

+3-10
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,20 @@
11
module.exports = class SiteDataPlugin {
2-
constructor (data, head = []) {
3-
this.data = data
4-
this.head = head
2+
constructor (tags = []) {
3+
this.tags = tags
54
}
65

76
apply (compiler) {
87
compiler.hooks.compilation.tap('vuepress-site-data', compilation => {
98
compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync('vuepress-site-data', (data, cb) => {
109
try {
11-
this.head.forEach(t => {
10+
this.tags.forEach(t => {
1211
data.head.push({
1312
tagName: t.tag,
1413
closeTag: !(t.tag === 'meta' || t.tag === 'link'),
1514
attributes: t.attributes,
1615
innerHTML: t.innerHTML || ''
1716
})
1817
})
19-
20-
data.head.push({
21-
tagName: 'script',
22-
closeTag: true,
23-
innerHTML: `window.VUEPRESS_DATA = ${JSON.stringify(this.data)}`
24-
})
2518
} catch (e) {
2619
return cb(e)
2720
}

Diff for: lib/webpack/baseConfig.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ const path = require('path')
33
module.exports = function createBaseConfig ({
44
sourceDir,
55
publicPath,
6-
themePath
6+
themePath,
7+
notFoundPath
78
}) {
89
const Config = require('webpack-chain')
910
const { VueLoaderPlugin } = require('vue-loader')
@@ -25,6 +26,8 @@ module.exports = function createBaseConfig ({
2526
.set('symlinks', true)
2627
.alias
2728
.set('~theme', themePath)
29+
.set('~notFound', notFoundPath)
30+
.set('~source', sourceDir)
2831
.end()
2932
.extensions
3033
.merge(['.js', '.jsx', '.vue', '.json'])

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"vuepress": "bin/vuepress.js"
88
},
99
"scripts": {
10-
"serve": "node bin/vuepress serve",
10+
"dev": "node bin/vuepress dev",
1111
"build": "node bin/vuepress build"
1212
},
1313
"repository": {
@@ -30,6 +30,7 @@
3030
"buble": "^0.19.3",
3131
"buble-loader": "^0.5.0",
3232
"chalk": "^2.3.2",
33+
"chokidar": "^2.0.3",
3334
"connect-history-api-fallback": "^1.5.0",
3435
"css-loader": "^0.28.11",
3536
"file-loader": "^1.1.11",

Diff for: yarn.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ cheerio@^1.0.0-rc.2:
595595
lodash "^4.15.0"
596596
parse5 "^3.0.1"
597597

598-
chokidar@^2.0.2:
598+
chokidar@^2.0.2, chokidar@^2.0.3:
599599
version "2.0.3"
600600
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
601601
dependencies:

0 commit comments

Comments
 (0)