perf(v2): skip runtime fileHash cache in prod & get timestamp asynchronously (#1951)

* skip hash calculation in prod when generating file

* perf: convert lastUpdated to be async process

* changelog
This commit is contained in:
Endi 2019-11-08 23:35:39 +07:00 committed by GitHub
parent e04c8f140f
commit 639d8d3eac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 107 additions and 42 deletions

View file

@ -16,7 +16,7 @@
"dependencies": {
"@docusaurus/mdx-loader": "^2.0.0-alpha.33",
"@docusaurus/utils": "^2.0.0-alpha.33",
"cross-spawn": "^7.0.1",
"execa": "^3.2.0",
"fs-extra": "^8.1.0",
"globby": "^10.0.1",
"import-fresh": "^3.1.0",

View file

@ -8,7 +8,6 @@
import fs from 'fs';
import path from 'path';
import shell from 'shelljs';
import spawn from 'cross-spawn';
import lastUpdate from '../lastUpdate';
@ -17,8 +16,8 @@ describe('lastUpdate', () => {
__dirname,
'__fixtures__/simple-site/docs/hello.md',
);
test('existing test file in repository with Git timestamp', () => {
const lastUpdateData = lastUpdate(existingFilePath);
test('existing test file in repository with Git timestamp', async () => {
const lastUpdateData = await lastUpdate(existingFilePath);
expect(lastUpdateData).not.toBeNull();
const {author, timestamp} = lastUpdateData;
@ -29,28 +28,37 @@ describe('lastUpdate', () => {
expect(typeof timestamp).toBe('number');
});
test('non-existing file', () => {
test('non-existing file', async () => {
const consoleMock = jest.spyOn(console, 'error');
consoleMock.mockImplementation();
const nonExistingFilePath = path.join(
__dirname,
'__fixtures__',
'.nonExisting',
);
expect(lastUpdate(null)).toBeNull();
expect(lastUpdate(undefined)).toBeNull();
expect(lastUpdate(nonExistingFilePath)).toBeNull();
expect(await lastUpdate(nonExistingFilePath)).toBeNull();
expect(consoleMock).toHaveBeenCalledTimes(1);
expect(consoleMock).toHaveBeenCalledWith(
new Error(
`Command failed with exit code 128: git log -1 --format=%ct, %an ${nonExistingFilePath}`,
),
);
expect(await lastUpdate(null)).toBeNull();
expect(await lastUpdate(undefined)).toBeNull();
consoleMock.mockRestore();
});
test('temporary created file that has no git timestamp', () => {
test('temporary created file that has no git timestamp', async () => {
const tempFilePath = path.join(__dirname, '__fixtures__', '.temp');
fs.writeFileSync(tempFilePath, 'Lorem ipsum :)');
expect(lastUpdate(tempFilePath)).toBeNull();
expect(await lastUpdate(tempFilePath)).toBeNull();
fs.unlinkSync(tempFilePath);
});
test('Git does not exist', () => {
test('Git does not exist', async () => {
const mock = jest.spyOn(shell, 'which').mockImplementationOnce(() => null);
const consoleMock = jest.spyOn(console, 'warn').mockImplementation();
const lastUpdateData = lastUpdate(existingFilePath);
const lastUpdateData = await lastUpdate(existingFilePath);
expect(lastUpdateData).toBeNull();
expect(consoleMock).toHaveBeenLastCalledWith(
'Sorry, the docs plugin last update options require Git.',
@ -59,17 +67,4 @@ describe('lastUpdate', () => {
consoleMock.mockRestore();
mock.mockRestore();
});
test('Error', () => {
const mock = jest.spyOn(spawn, 'sync').mockImplementationOnce(() => {
throw new Error('PERMISSION Error');
});
const consoleMock = jest.spyOn(console, 'error').mockImplementation();
const lastUpdateData = lastUpdate('/fake/path/');
expect(lastUpdateData).toBeNull();
expect(consoleMock).toHaveBeenLastCalledWith(new Error('PERMISSION Error'));
consoleMock.mockRestore();
mock.mockRestore();
});
});

View file

@ -6,7 +6,7 @@
*/
import shell from 'shelljs';
import spawn from 'cross-spawn';
import execa from 'execa';
type FileLastUpdateData = {timestamp?: number; author?: string};
@ -14,9 +14,12 @@ const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(\d+), (.+)$/;
let showedGitRequirementError = false;
export default function getFileLastUpdate(
filePath: string,
): FileLastUpdateData | null {
export default async function getFileLastUpdate(
filePath?: string,
): Promise<FileLastUpdateData | null> {
if (!filePath) {
return null;
}
function getTimestampAndAuthor(str: string): FileLastUpdateData | null {
if (!str) {
return null;
@ -39,12 +42,13 @@ export default function getFileLastUpdate(
return null;
}
const result = spawn
.sync('git', ['log', '-1', '--format=%ct, %an', filePath])
.stdout.toString()
.trim();
return getTimestampAndAuthor(result);
const {stdout} = await execa('git', [
'log',
'-1',
'--format=%ct, %an',
filePath,
]);
return getTimestampAndAuthor(stdout);
} catch (error) {
console.error(error);
}

View file

@ -112,7 +112,7 @@ export default async function processMetadata({
// Use fake data in dev for faster development
const fileLastUpdateData =
process.env.NODE_ENV === 'production'
? lastUpdate(filePath)
? await lastUpdate(filePath)
: {
author: 'Author',
timestamp: '1539502055',