Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(tag/helper): memoize #4789

Merged
merged 4 commits into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/plugins/helper/css.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const { htmlTag, url_for } = require('hexo-util');
const { default: moize } = require('moize');

const flatten = function(arr, result = []) {
for (const i in arr) {
Expand Down Expand Up @@ -35,4 +36,7 @@ function cssHelper(...args) {
return result;
}

module.exports = cssHelper;
module.exports = moize(cssHelper, {
maxSize: 10,
isDeepEqual: true
});
3 changes: 2 additions & 1 deletion lib/plugins/helper/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const moment = require('moment-timezone');
const { isMoment } = moment;
const { default: moize } = require('moize');

const isDate = value =>
typeof value === 'object' && value instanceof Date && !isNaN(value.getTime());
Expand Down Expand Up @@ -93,4 +94,4 @@ exports.full_date = fullDateHelper;
exports.relative_date = relativeDateHelper;
exports.time_tag = timeTagHelper;
exports.moment = moment;
exports.toMomentLocale = toMomentLocale;
exports.toMomentLocale = moize.shallow(toMomentLocale);
24 changes: 14 additions & 10 deletions lib/plugins/helper/feed_tag.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
'use strict';

const { url_for } = require('hexo-util');
const { default: moize } = require('moize');

const feedFn = (str = '') => {
if (str) return str.replace(/2$/, '');
return str;
};

function feedTagHelper(path, options = {}) {
const { config } = this;
const title = options.title || config.title;
function makeFeedTag(path, options = {}, configFeed, configTitle) {
const title = options.title || configTitle;

if (path) {
if (typeof path !== 'string') throw new TypeError('path must be a string!');
Expand All @@ -26,16 +26,15 @@ function feedTagHelper(path, options = {}) {
return `<link rel="alternate" href="${url_for.call(this, path)}" title="${title}" ${typeAttr}>`;
}

if (config.feed) {
const { feed } = config;
if (feed.type && feed.path) {
if (typeof feed.type === 'string') {
return `<link rel="alternate" href="${url_for.call(this, feed.path)}" title="${title}" type="application/${feedFn(feed.type)}+xml">`;
if (configFeed) {
if (configFeed.type && configFeed.path) {
if (typeof configFeed.type === 'string') {
return `<link rel="alternate" href="${url_for.call(this, configFeed.path)}" title="${title}" type="application/${feedFn(configFeed.type)}+xml">`;
}

let result = '';
for (const i in feed.type) {
result += `<link rel="alternate" href="${url_for.call(this, feed.path[i])}" title="${title}" type="application/${feedFn(feed.type[i])}+xml">`;
for (const i in configFeed.type) {
result += `<link rel="alternate" href="${url_for.call(this, configFeed.path[i])}" title="${title}" type="application/${feedFn(configFeed.type[i])}+xml">`;
}
return result;
}
Expand All @@ -44,4 +43,9 @@ function feedTagHelper(path, options = {}) {
return '';
}

function feedTagHelper(path, options = {}) {
const { config } = this;
return moize.deep(makeFeedTag.bind(this))(path, options, config.feed, config.title);
}

module.exports = feedTagHelper;
6 changes: 5 additions & 1 deletion lib/plugins/helper/js.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const { htmlTag, url_for } = require('hexo-util');
const { default: moize } = require('moize');

/* flatten() to be replaced by Array.flat()
after Node 10 has reached EOL */
Expand Down Expand Up @@ -37,4 +38,7 @@ function jsHelper(...args) {
return result;
}

module.exports = jsHelper;
module.exports = moize(jsHelper, {
maxSize: 10,
isDeepEqual: true
});
20 changes: 19 additions & 1 deletion lib/plugins/helper/list_tags.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const { url_for, escapeHTML } = require('hexo-util');
const { default: moize } = require('moize');

function listTagsHelper(tags, options) {
if (!options && (!tags || !Object.prototype.hasOwnProperty.call(tags, 'length'))) {
Expand Down Expand Up @@ -92,4 +93,21 @@ function listTagsHelper(tags, options) {
return result;
}

module.exports = listTagsHelper;
function listTagsHelperFactory(tags, options) {
const transformArgs = () => {
if (!options && (!tags || !Object.prototype.hasOwnProperty.call(tags, 'length'))) {
options = tags;
tags = this.site.tags;
}

return [tags.toArray(), options];
};

return moize(listTagsHelper.bind(this), {
maxSize: 5,
isDeepEqual: true,
transformArgs
}).call(this, tags, options);
}

module.exports = listTagsHelperFactory;
3 changes: 2 additions & 1 deletion lib/plugins/helper/mail_to.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { htmlTag } = require('hexo-util');
const qs = require('querystring');
const { default: moize } = require('moize');

function mailToHelper(path, text, options = {}) {
if (Array.isArray(path)) path = path.join(',');
Expand Down Expand Up @@ -33,4 +34,4 @@ function mailToHelper(path, text, options = {}) {
return htmlTag('a', attrs, text);
}

module.exports = mailToHelper;
module.exports = moize.deep(mailToHelper);
SukkaW marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 4 additions & 3 deletions lib/plugins/helper/open_graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

const { parse, resolve } = require('url');
const { isMoment, isDate } = require('moment');
const { encodeURL, prettyUrls, htmlTag, stripHTML, escapeHTML, Cache } = require('hexo-util');
const { encodeURL, prettyUrls, htmlTag, stripHTML, escapeHTML } = require('hexo-util');
const { default: moize } = require('moize');

const localeMap = {
'en': 'en_US',
Expand All @@ -20,8 +21,8 @@ const localeMap = {
'tr': 'tr_TR',
'vi': 'vi_VN'
};
const localeCache = new Cache();
const localeToTerritory = str => localeCache.apply(str, () => {

const localeToTerritory = moize.shallow(str => {
if (str.length === 2 && localeMap[str]) return localeMap[str];

if (str.length === 5) {
Expand Down
4 changes: 3 additions & 1 deletion lib/plugins/helper/search_form.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const { default: moize } = require('moize');

function searchFormHelper(options = {}) {
const { config } = this;
const className = options.class || 'search-form';
Expand All @@ -8,4 +10,4 @@ function searchFormHelper(options = {}) {
return `<form action="//google.com/search" method="get" accept-charset="UTF-8" class="${className}"><input type="search" name="q" class="${className}-input"${text ? ` placeholder="${text}"` : ''}>${button ? `<button type="submit" class="${className}-submit">${typeof button === 'string' ? button : text}</button>` : ''}<input type="hidden" name="sitesearch" value="${config.url}"></form>`;
}

module.exports = searchFormHelper;
module.exports = moize.deep(searchFormHelper);
20 changes: 19 additions & 1 deletion lib/plugins/helper/tagcloud.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const { Color, url_for } = require('hexo-util');
const { default: moize } = require('moize');

function tagcloudHelper(tags, options) {
if (!options && (!tags || !Object.prototype.hasOwnProperty.call(tags, 'length'))) {
Expand Down Expand Up @@ -74,4 +75,21 @@ function tagcloudHelper(tags, options) {
return result.join(separator);
}

module.exports = tagcloudHelper;
function tagcloudHelperFactory(tags, options) {
const transformArgs = () => {
if (!options && (!tags || !Object.prototype.hasOwnProperty.call(tags, 'length'))) {
options = tags;
tags = this.site.tags;
}

return [tags.toArray(), options];
};

return moize(tagcloudHelper.bind(this), {
maxSize: 5,
isDeepEqual: true,
transformArgs
}).call(this, tags, options);
}

module.exports = tagcloudHelperFactory;
24 changes: 24 additions & 0 deletions lib/plugins/tag/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const { default: moize } = require('moize');

module.exports = ctx => {
const { tag } = ctx.extend;

Expand Down Expand Up @@ -52,3 +54,25 @@ module.exports = ctx => {

tag.register('youtube', require('./youtube'));
};

// Use WeakMap to track different ctx (in case there is any)
const moized = new WeakMap();

module.exports.postFindOneFactory = function postFindOneFactory(ctx) {
jiangtj marked this conversation as resolved.
Show resolved Hide resolved
if (moized.has(ctx)) {
return moized.get(ctx);
}

const moizedPostFindOne = moize(createPostFindOne(ctx), {
isDeepEqual: true,
maxSize: 20
});
moized.set(ctx, moizedPostFindOne);

return moizedPostFindOne;
};

function createPostFindOne(ctx) {
const Post = ctx.model('Post');
return Post.findOne.bind(Post);
}
5 changes: 2 additions & 3 deletions lib/plugins/tag/post_link.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { encodeURL, escapeHTML } = require('hexo-util');
const { resolve } = require('url');
const { postFindOneFactory } = require('./');

/**
* Post link tag
Expand All @@ -10,8 +11,6 @@ const { resolve } = require('url');
* {% post_link slug [title] [escape] %}
*/
module.exports = ctx => {
const Post = ctx.model('Post');

return function postLinkTag(args) {
const error = `<a href="#">Post not found: ${args.join(' ') || 'Invalid post_link'}</a>`;
const slug = args.shift();
Expand All @@ -24,7 +23,7 @@ module.exports = ctx => {
escape = 'true';
}

const post = Post.findOne({slug});
const post = postFindOneFactory(ctx)({ slug });
if (!post) return error;

let title = args.length ? args.join(' ') : post.title;
Expand Down
5 changes: 2 additions & 3 deletions lib/plugins/tag/post_path.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { resolve } = require('url');
const { encodeURL } = require('hexo-util');
const { postFindOneFactory } = require('./');

/**
* Post path tag
Expand All @@ -10,13 +11,11 @@ const { encodeURL } = require('hexo-util');
* {% post_path slug %}
*/
module.exports = ctx => {
const Post = ctx.model('Post');

return function postPathTag(args) {
const slug = args.shift();
if (!slug) return;

const post = Post.findOne({slug});
const post = postFindOneFactory(ctx)({ slug });
if (!post) return;

const link = encodeURL(resolve(ctx.config.root, post.path));
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"hexo-util": "^2.4.0",
"js-yaml": "^4.0.0",
"micromatch": "^4.0.2",
"moize": "^6.1.0",
"moment": "^2.22.2",
"moment-timezone": "^0.5.21",
"nanocolors": "^0.2.12",
Expand Down