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

breaking(v2): minimum required nodejs version 8.9->8.10 so we can use es2017 #2045

Merged
merged 1 commit into from
Nov 25, 2019

Conversation

endiliey
Copy link
Contributor

Motivation

Node >= 8.10.0 support 100% ES2017 with native async await
while
Node 8.9.0 only support 100% ES6, 100% ES2016 and 73% ES2017.

Because of this, previously our TypeScript compiler always have to compile to ES6 and polyfill the await function.

For example, our generated js files for docusaurus/core/src/server/index is like this previously

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@docusaurus/utils");
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const constants_1 = require("../constants");
const client_modules_1 = require("./client-modules");
const config_1 = require("./config");
const plugins_1 = require("./plugins");
const presets_1 = require("./presets");
const routes_1 = require("./routes");
const themes_1 = require("./themes");
function loadContext(siteDir) {
    const generatedFilesDir = path_1.default.resolve(siteDir, constants_1.GENERATED_FILES_DIR_NAME);
    const siteConfig = config_1.loadConfig(siteDir);
    const outDir = path_1.default.resolve(siteDir, constants_1.BUILD_DIR_NAME);
    const { baseUrl } = siteConfig;
    return {
        siteDir,
        generatedFilesDir,
        siteConfig,
        outDir,
        baseUrl,
    };
}
exports.loadContext = loadContext;
function loadPluginConfigs(context) {
    const { plugins: presetPlugins, themes: presetThemes } = presets_1.loadPresets(context);
    const { siteConfig } = context;
    return [
        ...presetPlugins,
        ...presetThemes,
        // Site config should the highest priority.
        ...(siteConfig.plugins || []),
        ...(siteConfig.themes || []),
    ];
}
exports.loadPluginConfigs = loadPluginConfigs;
function load(siteDir) {
    return __awaiter(this, void 0, void 0, function* () {
        // Context
        const context = loadContext(siteDir);
        const { generatedFilesDir, siteConfig, outDir, baseUrl } = context;
        const genSiteConfig = utils_1.generate(generatedFilesDir, constants_1.CONFIG_FILE_NAME, `export default ${JSON.stringify(siteConfig, null, 2)};`);
        // Plugins
        const pluginConfigs = loadPluginConfigs(context);
        const { plugins, pluginsRouteConfigs } = yield plugins_1.loadPlugins({
            pluginConfigs,
            context,
        });
        // Themes.
        const fallbackTheme = path_1.default.resolve(__dirname, '../client/theme-fallback');
        const pluginThemes = lodash_1.default.compact(plugins.map(plugin => plugin.getThemePath && plugin.getThemePath()));
        const userTheme = path_1.default.resolve(siteDir, constants_1.THEME_PATH);
        const alias = themes_1.loadThemeAlias([fallbackTheme, ...pluginThemes, userTheme]);
        // Make a fake plugin to resolve aliased theme components.
        plugins.push({
            name: 'docusaurus-bootstrap-plugin',
            configureWebpack: () => ({
                resolve: {
                    alias,
                },
            }),
        });
        // Load client modules.
        const clientModules = client_modules_1.loadClientModules(plugins);
        const genClientModules = utils_1.generate(generatedFilesDir, 'client-modules.js', `export default [\n${clientModules
            // import() is async so we use require() because client modules can have
            // CSS and the order matters for loading CSS.
            .map(module => `  require("${module}"),`)
            .join('\n')}\n];\n`);
        // Routing
        const { registry, routesChunkNames, routesConfig, routesPaths, } = yield routes_1.loadRoutes(pluginsRouteConfigs);
        const genRegistry = utils_1.generate(generatedFilesDir, 'registry.js', `export default {
${Object.keys(registry)
            .sort()
            .map(key => `  '${key}': [${registry[key].loader}, "${registry[key].modulePath}", require.resolveWeak("${registry[key].modulePath}")],`)
            .join('\n')}};\n`);
        const genRoutesChunkNames = utils_1.generate(generatedFilesDir, 'routesChunkNames.json', JSON.stringify(routesChunkNames, null, 2));
        const genRoutes = utils_1.generate(generatedFilesDir, 'routes.js', routesConfig);
        yield Promise.all([
            genClientModules,
            genSiteConfig,
            genRegistry,
            genRoutesChunkNames,
            genRoutes,
        ]);
        const props = {
            siteConfig,
            siteDir,
            outDir,
            baseUrl,
            generatedFilesDir,
            routesPaths,
            plugins,
        };
        return props;
    });
}
exports.load = load;

After compiling to ES2017, it can utilize node's own native async await which is more optimized

var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@docusaurus/utils");
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const constants_1 = require("../constants");
const client_modules_1 = require("./client-modules");
const config_1 = require("./config");
const plugins_1 = require("./plugins");
const presets_1 = require("./presets");
const routes_1 = require("./routes");
const themes_1 = require("./themes");
function loadContext(siteDir) {
    const generatedFilesDir = path_1.default.resolve(siteDir, constants_1.GENERATED_FILES_DIR_NAME);
    const siteConfig = config_1.loadConfig(siteDir);
    const outDir = path_1.default.resolve(siteDir, constants_1.BUILD_DIR_NAME);
    const { baseUrl } = siteConfig;
    return {
        siteDir,
        generatedFilesDir,
        siteConfig,
        outDir,
        baseUrl,
    };
}
exports.loadContext = loadContext;
function loadPluginConfigs(context) {
    const { plugins: presetPlugins, themes: presetThemes } = presets_1.loadPresets(context);
    const { siteConfig } = context;
    return [
        ...presetPlugins,
        ...presetThemes,
        // Site config should the highest priority.
        ...(siteConfig.plugins || []),
        ...(siteConfig.themes || []),
    ];
}
exports.loadPluginConfigs = loadPluginConfigs;
async function load(siteDir) {
    // Context
    const context = loadContext(siteDir);
    const { generatedFilesDir, siteConfig, outDir, baseUrl } = context;
    const genSiteConfig = utils_1.generate(generatedFilesDir, constants_1.CONFIG_FILE_NAME, `export default ${JSON.stringify(siteConfig, null, 2)};`);
    // Plugins
    const pluginConfigs = loadPluginConfigs(context);
    const { plugins, pluginsRouteConfigs } = await plugins_1.loadPlugins({
        pluginConfigs,
        context,
    });
    // Themes.
    const fallbackTheme = path_1.default.resolve(__dirname, '../client/theme-fallback');
    const pluginThemes = lodash_1.default.compact(plugins.map(plugin => plugin.getThemePath && plugin.getThemePath()));
    const userTheme = path_1.default.resolve(siteDir, constants_1.THEME_PATH);
    const alias = themes_1.loadThemeAlias([fallbackTheme, ...pluginThemes, userTheme]);
    // Make a fake plugin to resolve aliased theme components.
    plugins.push({
        name: 'docusaurus-bootstrap-plugin',
        configureWebpack: () => ({
            resolve: {
                alias,
            },
        }),
    });
    // Load client modules.
    const clientModules = client_modules_1.loadClientModules(plugins);
    const genClientModules = utils_1.generate(generatedFilesDir, 'client-modules.js', `export default [\n${clientModules
        // import() is async so we use require() because client modules can have
        // CSS and the order matters for loading CSS.
        .map(module => `  require("${module}"),`)
        .join('\n')}\n];\n`);
    // Routing
    const { registry, routesChunkNames, routesConfig, routesPaths, } = await routes_1.loadRoutes(pluginsRouteConfigs);
    const genRegistry = utils_1.generate(generatedFilesDir, 'registry.js', `export default {
${Object.keys(registry)
        .sort()
        .map(key => `  '${key}': [${registry[key].loader}, "${registry[key].modulePath}", require.resolveWeak("${registry[key].modulePath}")],`)
        .join('\n')}};\n`);
    const genRoutesChunkNames = utils_1.generate(generatedFilesDir, 'routesChunkNames.json', JSON.stringify(routesChunkNames, null, 2));
    const genRoutes = utils_1.generate(generatedFilesDir, 'routes.js', routesConfig);
    await Promise.all([
        genClientModules,
        genSiteConfig,
        genRegistry,
        genRoutesChunkNames,
        genRoutes,
    ]);
    const props = {
        siteConfig,
        siteDir,
        outDir,
        baseUrl,
        generatedFilesDir,
        routesPaths,
        plugins,
    };
    return props;
}
exports.load = load;

Extra benefit is that our npm package should be lower in size due to removal of polyfills

Anyway, node 8.X is going for EOL this 31 December 2019. I think most people is in v10 or v12 anyway

Have you read the Contributing Guidelines on pull requests?

yes

Test Plan

  • CI should all pass
  • Netlify
  • Local dev + hot reload ok

@endiliey endiliey added pr: breaking change Existing sites may not build successfully in the new version. Description contains more details. pr: maintenance This PR does not produce any behavior differences to end users when upgrading. labels Nov 25, 2019
@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label Nov 25, 2019
@docusaurus-bot
Copy link
Contributor

Deploy preview for docusaurus-2 ready!

Built with commit bda7e74

https://deploy-preview-2045--docusaurus-2.netlify.com

@docusaurus-bot
Copy link
Contributor

Deploy preview for docusaurus-preview ready!

Built with commit bda7e74

https://deploy-preview-2045--docusaurus-preview.netlify.com

@yangshun yangshun merged commit 421f862 into master Nov 25, 2019
@yangshun yangshun deleted the endi/es2017 branch November 25, 2019 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Signed Facebook CLA pr: breaking change Existing sites may not build successfully in the new version. Description contains more details. pr: maintenance This PR does not produce any behavior differences to end users when upgrading.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants