mirror of
https://github.com/facebook/docusaurus.git
synced 2025-08-03 16:59:06 +02:00
feat: prototype blog post generation in dev server
This commit is contained in:
parent
8cbd23d690
commit
7ecd4c9bef
9 changed files with 112 additions and 31 deletions
13
lib/core/blogPost.js
Normal file
13
lib/core/blogPost.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
const React = require('react');
|
||||
import blogDatas from '@generated/blogDatas';
|
||||
|
||||
// inner blog component for the article itself, without sidebar/header/footer
|
||||
class BlogPost extends React.Component {
|
||||
render() {
|
||||
const {match} = this.props;
|
||||
const post = blogDatas.find(blog => blog.path === match.path);
|
||||
return <div className="post">{post && post.content}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BlogPost;
|
|
@ -1,30 +1,30 @@
|
|||
import React from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import {BrowserRouter, Route, Switch} from 'react-router-dom';
|
||||
import Hello from '@theme/hello';
|
||||
import Layout from '@theme/layout';
|
||||
import {BrowserRouter, Route, Switch, Link} from 'react-router-dom';
|
||||
import BlogPost from './blogPost';
|
||||
import blogDatas from '@generated/blogDatas';
|
||||
|
||||
class App extends React.Component {
|
||||
render() {
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: Hello
|
||||
},
|
||||
{
|
||||
path: '/layout',
|
||||
component: Layout
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div>
|
||||
<Switch>
|
||||
{routes.map(({path, component}) => (
|
||||
<Route key={path} exact path={path} component={component} />
|
||||
{blogDatas.map(({path}) => (
|
||||
<Route key={path} exact path={path} component={BlogPost} />
|
||||
))}
|
||||
</Switch>
|
||||
<div>
|
||||
{blogDatas.map(({path}) => {
|
||||
return (
|
||||
<div>
|
||||
<Link key={path} to={path}>
|
||||
{path}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
|
34
lib/dev.js
34
lib/dev.js
|
@ -3,11 +3,22 @@ const fs = require('fs-extra');
|
|||
const chalk = require('chalk');
|
||||
const webpack = require('webpack');
|
||||
const chokidar = require('chokidar');
|
||||
const convert = require('koa-connect')
|
||||
const range = require('koa-range')
|
||||
const history = require('connect-history-api-fallback')
|
||||
const portfinder = require('portfinder')
|
||||
const serve = require('webpack-serve');
|
||||
const webpackNiceLog = require('webpack-nicelog');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const load = require('./loader');
|
||||
const createDevConfig = require('./webpack/dev');
|
||||
|
||||
async function getPort (port) {
|
||||
portfinder.basePort = parseInt(port) || 8080
|
||||
port = await portfinder.getPortPromise()
|
||||
return port
|
||||
}
|
||||
|
||||
module.exports = async function dev(sourceDir, cliOptions = {}) {
|
||||
// load site props from preprocessed files in source directory
|
||||
const props = await load(sourceDir);
|
||||
|
@ -18,7 +29,7 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
|
|||
console.error(chalk.red(err.stack));
|
||||
});
|
||||
};
|
||||
const fsWatcher = chokidar.watch(['**/*.md'], {
|
||||
const fsWatcher = chokidar.watch(['**/*.md', '.blogi/config.js'], {
|
||||
cwd: sourceDir,
|
||||
ignoreInitial: true
|
||||
});
|
||||
|
@ -31,7 +42,7 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
|
|||
// resolve webpack config
|
||||
let config = createDevConfig(props);
|
||||
|
||||
const port = cliOptions.port || 8080;
|
||||
const port = await getPort(cliOptions.port);
|
||||
const {publicPath} = props;
|
||||
|
||||
config.plugin('WebpackNiceLog').use(webpackNiceLog, [
|
||||
|
@ -46,6 +57,15 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
|
|||
}
|
||||
]);
|
||||
|
||||
config.plugin('html-webpack-plugin').use(HtmlWebpackPlugin, [
|
||||
{
|
||||
inject: false,
|
||||
hash: true,
|
||||
template: path.resolve(__dirname, 'core/index.html'),
|
||||
filename: 'index.html'
|
||||
}
|
||||
]);
|
||||
|
||||
// create compiler from generated webpack config
|
||||
config = config.toConfig();
|
||||
const compiler = webpack(config);
|
||||
|
@ -65,7 +85,15 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
|
|||
logLevel: 'error'
|
||||
},
|
||||
logLevel: 'error',
|
||||
port
|
||||
port,
|
||||
add: app => {
|
||||
app.use(range) // enable range request https://tools.ietf.org/html/rfc7233
|
||||
app.use(convert(history({
|
||||
rewrites: [
|
||||
{ from: /\.html$/, to: '/' }
|
||||
]
|
||||
})))
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -10,6 +10,15 @@ module.exports = async function load(sourceDir) {
|
|||
// extract data from all blog files
|
||||
const blogDatas = await loadBlog(sourceDir);
|
||||
|
||||
fs.writeFile(
|
||||
path.resolve(__dirname, '../generated/blogDatas.js'),
|
||||
`${'/**\n' +
|
||||
' * @' +
|
||||
'generated\n' +
|
||||
' */\n' +
|
||||
'module.exports = '}${JSON.stringify(blogDatas, null, 2)};\n`
|
||||
);
|
||||
|
||||
// resolve outDir
|
||||
const outDir = siteConfig.dest
|
||||
? path.resolve(siteConfig.dest)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const Config = require('webpack-chain');
|
||||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
module.exports = function createBaseConfig(props) {
|
||||
const {outDir, themePath, sourceDir, publicPath} = props;
|
||||
|
@ -43,14 +42,5 @@ module.exports = function createBaseConfig(props) {
|
|||
presets: ['env', 'react']
|
||||
});
|
||||
|
||||
config.plugin('html-webpack-plugin').use(HtmlWebpackPlugin, [
|
||||
{
|
||||
inject: false,
|
||||
hash: true,
|
||||
template: path.resolve(__dirname, '../core/index.html'),
|
||||
filename: 'index.html'
|
||||
}
|
||||
]);
|
||||
|
||||
return config;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue