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

refactor: drop lodash for lib/theme #3807

Closed
wants to merge 10 commits into from
4 changes: 2 additions & 2 deletions lib/theme/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const util = require('util');
const Box = require('../box');
const View = require('./view');
const I18n = require('hexo-i18n');
const _ = require('lodash');

function Theme(ctx) {
Reflect.apply(Box, this, [ctx, ctx.theme_dir]);
Expand All @@ -28,7 +27,8 @@ function Theme(ctx) {
languages.push('default');

this.i18n = new I18n({
languages: _(languages).compact().uniq().value()
// languages: Array.from(new Set(languages.filter(Boolean)))
languages: [...new Set(languages.filter(Boolean))]
Copy link
Contributor

@curbengh curbengh Oct 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about Array.from(new Set(languages.filter(Boolean)))?

I wonder if value() is needed, I can't find it in lodash doc, perhaps it's a function of languages?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value() is a lodash method, which is used to get value from lodash wrapped prototype chain.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have make a benchmark at jsPerf: https://jsperf.com/lodash-uniq-vs-javascript-set/1

It seems the diffrence between Array.from & spread syntax is negligible, at least in browser.

Copy link
Contributor

@curbengh curbengh Oct 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

The travis benchmark showed the spread syntax is the source of regression. I noticed you reverted the last commit; to confirm the source?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the diffrence between Array.from & spread syntax is negligible, at least in browser.

Similar result in travis too. Can you try revert back to lodash just for this line? to test whether Set() is the culprit.

Copy link
Contributor

@curbengh curbengh Oct 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that doesn't explain why lodash is faster in view.js.


btw, as for the lib/theme, I think it's fine to use Set() since languages array would only have 2 elements max, so it wouldn't (and shouldn't) make any difference.

Copy link
Member Author

@SukkaW SukkaW Oct 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@curbengh I have done through some investigation about performance of Object.assign. It seems that Object.assign will meet performance issue when facing large object. Even Node.js itself is still using the deprecated util._extend, because it is still a lot more faster than Object.assign.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit more interesting... Even if I replace Object.assign with lodash.assign, the impact is still there. So maybe the problem is at Object.getPrototypeOf..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like the last suspect now. what about return Object.assign({}, locals, locals.prototype, data, { ? (source)

Copy link
Member Author

@SukkaW SukkaW Oct 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@curbengh In fact I have tried local.prototype at very beginning but it won't pass the test. The locals here is differentwith a constructor.

});

const viewFn = function(path, data) {
Expand Down
10 changes: 5 additions & 5 deletions lib/theme/view.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use strict';

const { dirname, extname, join } = require('path');
const assignIn = require('lodash/assignIn');
const omit = require('lodash/omit');
const yfm = require('hexo-front-matter');
const Promise = require('bluebird');
const assign = require('lodash/assign');

function View(path, data) {
this.path = path;
Expand Down Expand Up @@ -61,7 +60,9 @@ View.prototype.renderSync = function(options = {}) {
};

View.prototype._buildLocals = function(locals) {
return assignIn({}, locals, omit(this.data, ['layout', '_content']), {
// eslint-disable-next-line no-unused-vars
const { layout, _content, ...data } = this.data;
return assign({}, locals, Object.getPrototypeOf(locals), data, {
filename: this.source
});
};
Expand All @@ -70,8 +71,7 @@ View.prototype._bindHelpers = function(locals) {
const helpers = this._helper.list();
const keys = Object.keys(helpers);

for (let i = 0, len = keys.length; i < len; i++) {
const key = keys[i];
for (const key of keys) {
locals[key] = helpers[key].bind(locals);
}

Expand Down