perf(v2): smaller bundlesize by embedding metadata to content (#2088)

* wip embed metadata to content

* embed metadata in blog as well

* refactor

* update test

* yarn lock

* avoid overwriting file everytime we run new nodejs process

* nits
This commit is contained in:
Endi 2019-12-06 12:34:21 +07:00 committed by GitHub
parent 32c9d07b90
commit 7f8aca2ddc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 236 additions and 200 deletions

View file

@ -10,7 +10,7 @@ import globby from 'globby';
import path from 'path';
import {Feed} from 'feed';
import {PluginOptions, BlogPost, DateLink} from './types';
import {parse, normalizeUrl} from '@docusaurus/utils';
import {parse, normalizeUrl, aliasedSitePath} from '@docusaurus/utils';
import {LoadContext} from '@docusaurus/types';
export function truncate(fileString: string, truncateMarker: RegExp | string) {
@ -100,10 +100,8 @@ export async function generateBlogPosts(
await Promise.all(
blogFiles.map(async (relativeSource: string) => {
// Cannot use path.join() as it resolves '../' and removes the '@site'.
// Let webpack loader resolve it.
const source = path.join(blogDir, relativeSource);
const aliasedSource = `@site/${path.relative(siteDir, source)}`;
const aliasedSource = aliasedSitePath(source, siteDir);
const blogFileName = path.basename(relativeSource);
const fileString = await fs.readFile(source, 'utf-8');

View file

@ -14,7 +14,7 @@ import {
PluginOptions,
BlogTags,
BlogContent,
BlogItemsToModules,
BlogItemsToMetadata,
TagsModule,
BlogPaginated,
FeedType,
@ -215,7 +215,7 @@ export default function pluginContentBlog(
} = options;
const aliasedSource = (source: string) =>
`@docusaurus-plugin-content-blog/${path.relative(dataDir, source)}`;
`~blog/${path.relative(dataDir, source)}`;
const {addRoute, createData} = actions;
const {
blogPosts,
@ -224,41 +224,31 @@ export default function pluginContentBlog(
blogTagsListPath,
} = blogContents;
const blogItemsToModules: BlogItemsToModules = {};
const blogItemsToMetadata: BlogItemsToMetadata = {};
// Create routes for blog entries.
const blogItems = await Promise.all(
await Promise.all(
blogPosts.map(async blogPost => {
const {id, metadata} = blogPost;
const {permalink} = metadata;
const metadataPath = await createData(
`${docuHash(permalink)}.json`,
await createData(
// Note that this created data path must be in sync with markdownLoader.ts metadataPath
`${docuHash(metadata.source)}.json`,
JSON.stringify(metadata, null, 2),
);
const temp = {
metadata,
metadataPath,
};
blogItemsToModules[id] = temp;
return temp;
addRoute({
path: metadata.permalink,
component: blogPostComponent,
exact: true,
modules: {
content: metadata.source,
},
});
blogItemsToMetadata[id] = metadata;
}),
);
blogItems.map(blogItem => {
const {metadata, metadataPath} = blogItem;
const {source, permalink} = metadata;
addRoute({
path: permalink,
component: blogPostComponent,
exact: true,
modules: {
content: source,
metadata: aliasedSource(metadataPath),
},
});
});
// Create routes for blog's paginated list entries.
await Promise.all(
blogListPaginated.map(async listPage => {
@ -275,20 +265,16 @@ export default function pluginContentBlog(
exact: true,
modules: {
items: items.map(postID => {
const {
metadata: postMetadata,
metadataPath,
} = blogItemsToModules[postID];
const metadata = blogItemsToMetadata[postID];
// To tell routes.js this is an import and not a nested object to recurse.
return {
content: {
__import: true,
path: postMetadata.source,
path: metadata.source,
query: {
truncated: true,
},
},
metadata: aliasedSource(metadataPath),
};
}),
metadata: aliasedSource(pageMetadataPath),
@ -327,19 +313,15 @@ export default function pluginContentBlog(
exact: true,
modules: {
items: items.map(postID => {
const {
metadata: postMetadata,
metadataPath,
} = blogItemsToModules[postID];
const metadata = blogItemsToMetadata[postID];
return {
content: {
__import: true,
path: postMetadata.source,
path: metadata.source,
query: {
truncated: true,
},
},
metadata: aliasedSource(metadataPath),
};
}),
metadata: aliasedSource(tagsMetadataPath),
@ -375,7 +357,7 @@ export default function pluginContentBlog(
return {
resolve: {
alias: {
'@docusaurus-plugin-content-blog': dataDir,
'~blog': dataDir,
},
},
module: {
@ -396,6 +378,8 @@ export default function pluginContentBlog(
{
loader: path.resolve(__dirname, './markdownLoader.js'),
options: {
dataDir,
siteDir: context.siteDir,
truncateMarker,
},
},

View file

@ -8,11 +8,14 @@
const {parseQuery, getOptions} = require('loader-utils');
import {loader} from 'webpack';
import {truncate} from './blogUtils';
import path from 'path';
import {readFile} from 'fs-extra';
import {aliasedSitePath, docuHash} from '@docusaurus/utils';
export = function(fileString: string) {
const callback = this.async();
const {truncateMarker}: {truncateMarker: RegExp | string} = getOptions(this);
const {truncateMarker, siteDir, dataDir} = getOptions(this);
let finalContent = fileString;
@ -21,5 +24,19 @@ export = function(fileString: string) {
if (truncated) {
finalContent = truncate(fileString, truncateMarker);
}
return callback && callback(null, finalContent);
// Read metadata & then embed it to this markdown content
// Note that metadataPath must be the same/ in-sync as the path from createData
const aliasedSource = aliasedSitePath(this.resourcePath, siteDir);
const metadataPath = path.join(dataDir, `${docuHash(aliasedSource)}.json`);
// Add metadataPath as dependency of this loader result so that we can recompile if metadata is changed
this.addDependency(metadataPath);
readFile(metadataPath, 'utf8', function(err, metadata) {
if (err) return callback && callback(err);
const metadataStr = `export const metadata = ${metadata};`;
callback && callback(null, finalContent + '\n' + metadataStr);
});
} as loader.Loader;

View file

@ -91,13 +91,8 @@ export interface Tag {
permalink: string;
}
export interface BlogItemsToModules {
[key: string]: MetaDataWithPath;
}
export interface MetaDataWithPath {
metadata: MetaData;
metadataPath: string;
export interface BlogItemsToMetadata {
[key: string]: MetaData;
}
export interface TagsModule {