mastodon
Este commit está contenido en:
467
development/mastodon/base_optimizer.js
Archivo normal
467
development/mastodon/base_optimizer.js
Archivo normal
@@ -0,0 +1,467 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
var _fs = require('fs');
|
||||
|
||||
var _os = require('os');
|
||||
|
||||
var _os2 = _interopRequireDefault(_os);
|
||||
|
||||
var _boom = require('boom');
|
||||
|
||||
var _boom2 = _interopRequireDefault(_boom);
|
||||
|
||||
var _miniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
|
||||
var _miniCssExtractPlugin2 = _interopRequireDefault(_miniCssExtractPlugin);
|
||||
|
||||
var _terserWebpackPlugin = require('terser-webpack-plugin');
|
||||
|
||||
var _terserWebpackPlugin2 = _interopRequireDefault(_terserWebpackPlugin);
|
||||
|
||||
var _webpack = require('webpack');
|
||||
|
||||
var _webpack2 = _interopRequireDefault(_webpack);
|
||||
|
||||
var _Stats = require('webpack/lib/Stats');
|
||||
|
||||
var _Stats2 = _interopRequireDefault(_Stats);
|
||||
|
||||
var _threadLoader = require('thread-loader');
|
||||
|
||||
var threadLoader = _interopRequireWildcard(_threadLoader);
|
||||
|
||||
var _webpackMerge = require('webpack-merge');
|
||||
|
||||
var _webpackMerge2 = _interopRequireDefault(_webpackMerge);
|
||||
|
||||
var _dynamic_dll_plugin = require('./dynamic_dll_plugin');
|
||||
|
||||
var _lodash = require('lodash');
|
||||
|
||||
var _utils = require('../utils');
|
||||
|
||||
var _public_path_placeholder = require('./public_path_placeholder');
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
const POSTCSS_CONFIG_PATH = require.resolve('./postcss.config');
|
||||
const BABEL_PRESET_PATH = require.resolve('@kbn/babel-preset/webpack_preset');
|
||||
const BABEL_EXCLUDE_RE = [/[\/\\](webpackShims|node_modules|bower_components)[\/\\]/];
|
||||
const STATS_WARNINGS_FILTER = new RegExp(['(export .* was not found in)', '|(chunk .* \\[mini-css-extract-plugin\\]\\\nConflicting order between:)'].join(''));
|
||||
|
||||
class BaseOptimizer {
|
||||
constructor(opts) {
|
||||
this.logWithMetadata = opts.logWithMetadata || (() => null);
|
||||
this.uiBundles = opts.uiBundles;
|
||||
this.profile = opts.profile || false;
|
||||
|
||||
switch (opts.sourceMaps) {
|
||||
case true:
|
||||
this.sourceMaps = 'source-map';
|
||||
break;
|
||||
|
||||
case 'fast':
|
||||
this.sourceMaps = 'cheap-module-eval-source-map';
|
||||
break;
|
||||
|
||||
default:
|
||||
this.sourceMaps = opts.sourceMaps || false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Run some pre loading in order to prevent
|
||||
// high delay when booting thread loader workers
|
||||
this.warmupThreadLoaderPool();
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (this.compiler) {
|
||||
return this;
|
||||
}
|
||||
|
||||
const compilerConfig = this.getConfig();
|
||||
this.compiler = (0, _webpack2.default)(compilerConfig);
|
||||
|
||||
// register the webpack compiler hooks
|
||||
// for the base optimizer
|
||||
this.registerCompilerHooks();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
registerCompilerHooks() {
|
||||
this.registerCompilerDoneHook();
|
||||
}
|
||||
|
||||
registerCompilerDoneHook() {
|
||||
this.compiler.hooks.done.tap('base_optimizer-done', stats => {
|
||||
// We are not done while we have an additional
|
||||
// compilation pass to run
|
||||
// We also don't need to emit the stats if we don't have
|
||||
// the profile option set
|
||||
if (!this.profile || stats.compilation.needAdditionalPass) {
|
||||
return;
|
||||
}
|
||||
|
||||
const path = this.uiBundles.resolvePath('stats.json');
|
||||
const content = JSON.stringify(stats.toJson());
|
||||
(0, _fs.writeFile)(path, content, function (err) {
|
||||
if (err) throw err;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
warmupThreadLoaderPool() {
|
||||
const baseModules = ['babel-loader', BABEL_PRESET_PATH];
|
||||
|
||||
const nonDistributableOnlyModules = !_utils.IS_KIBANA_DISTRIBUTABLE ? ['ts-loader'] : [];
|
||||
|
||||
threadLoader.warmup(
|
||||
// pool options, like passed to loader options
|
||||
// must match loader options to boot the correct pool
|
||||
this.getThreadLoaderPoolConfig(), [
|
||||
// modules to load on the pool
|
||||
...baseModules, ...nonDistributableOnlyModules]);
|
||||
}
|
||||
|
||||
getThreadPoolCpuCount() {
|
||||
const cpus = _os2.default.cpus();
|
||||
if (!cpus) {
|
||||
// sometimes this call returns undefined so we fall back to 1: https://github.com/nodejs/node/issues/19022
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Math.max(1, Math.min(cpus.length - 1, 7));
|
||||
}
|
||||
|
||||
getThreadLoaderPoolConfig() {
|
||||
// Calculate the node options from the NODE_OPTIONS env var
|
||||
const parsedNodeOptions = process.env.NODE_OPTIONS ? process.env.NODE_OPTIONS.split(/\s/) : [];
|
||||
|
||||
return {
|
||||
name: 'optimizer-thread-loader-main-pool',
|
||||
workers: 1,
|
||||
workerParallelJobs: 1,
|
||||
// This is a safe check in order to set
|
||||
// the parent node options applied from
|
||||
// the NODE_OPTIONS env var for every launched worker.
|
||||
// Otherwise, if the user sets max_old_space_size, as they
|
||||
// are used to, into NODE_OPTIONS, it won't affect the workers.
|
||||
workerNodeArgs: parsedNodeOptions,
|
||||
poolParallelJobs: 1,
|
||||
poolTimeout: this.uiBundles.isDevMode() ? Infinity : 2000
|
||||
};
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
function getStyleLoaderExtractor() {
|
||||
return [_miniCssExtractPlugin2.default.loader];
|
||||
}
|
||||
|
||||
function getStyleLoaders(preProcessors = [], postProcessors = []) {
|
||||
return [...postProcessors, {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
// importLoaders needs to know the number of loaders that follow this one,
|
||||
// so we add 1 (for the postcss-loader) to the length of the preProcessors
|
||||
// array that we merge into this array
|
||||
importLoaders: 1 + preProcessors.length
|
||||
}
|
||||
}, {
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: POSTCSS_CONFIG_PATH
|
||||
}
|
||||
}
|
||||
}, ...preProcessors];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a cache loader if we're running in dev mode. The reason we're not adding
|
||||
* the cache-loader when running in production mode is that it creates cache
|
||||
* files in optimize/.cache that are not necessary for distributable versions
|
||||
* of Kibana and just make compressing and extracting it more difficult.
|
||||
*/
|
||||
const maybeAddCacheLoader = (cacheName, loaders) => {
|
||||
if (_utils.IS_KIBANA_DISTRIBUTABLE) {
|
||||
return loaders;
|
||||
}
|
||||
|
||||
return [{
|
||||
loader: 'cache-loader',
|
||||
options: {
|
||||
cacheDirectory: this.uiBundles.getCacheDirectory(cacheName)
|
||||
}
|
||||
}, ...loaders];
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the selection rules for a loader that will only pass for
|
||||
* source files that are eligible for automatic transpilation.
|
||||
*/
|
||||
const createSourceFileResourceSelector = test => {
|
||||
return [{
|
||||
test,
|
||||
exclude: BABEL_EXCLUDE_RE.concat(this.uiBundles.getWebpackNoParseRules())
|
||||
}, {
|
||||
test,
|
||||
include: /[\/\\]node_modules[\/\\]x-pack[\/\\]/,
|
||||
exclude: /[\/\\]node_modules[\/\\]x-pack[\/\\](.+?[\/\\])*node_modules[\/\\]/
|
||||
}];
|
||||
};
|
||||
|
||||
const commonConfig = {
|
||||
mode: 'development',
|
||||
node: { fs: 'empty' },
|
||||
context: (0, _utils.fromRoot)('.'),
|
||||
cache: true,
|
||||
entry: this.uiBundles.toWebpackEntries(),
|
||||
|
||||
devtool: this.sourceMaps,
|
||||
profile: this.profile || false,
|
||||
|
||||
output: {
|
||||
path: this.uiBundles.getWorkingDir(),
|
||||
filename: '[name].bundle.js',
|
||||
sourceMapFilename: '[file].map',
|
||||
publicPath: _public_path_placeholder.PUBLIC_PATH_PLACEHOLDER,
|
||||
devtoolModuleFilenameTemplate: '[absolute-resource-path]'
|
||||
},
|
||||
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
commons: {
|
||||
name: 'commons',
|
||||
chunks: 'initial',
|
||||
minChunks: 2,
|
||||
reuseExistingChunk: true
|
||||
}
|
||||
}
|
||||
},
|
||||
noEmitOnErrors: true
|
||||
},
|
||||
|
||||
plugins: [new _dynamic_dll_plugin.DynamicDllPlugin({
|
||||
uiBundles: this.uiBundles,
|
||||
threadLoaderPoolConfig: this.getThreadLoaderPoolConfig(),
|
||||
logWithMetadata: this.logWithMetadata
|
||||
}), new _miniCssExtractPlugin2.default({
|
||||
filename: '[name].style.css'
|
||||
}),
|
||||
|
||||
// replace imports for `uiExports/*` modules with a synthetic module
|
||||
// created by create_ui_exports_module.js
|
||||
new _webpack2.default.NormalModuleReplacementPlugin(/^uiExports\//, resource => {
|
||||
// the map of uiExport types to module ids
|
||||
const extensions = this.uiBundles.getAppExtensions();
|
||||
|
||||
// everything following the first / in the request is
|
||||
// treated as a type of appExtension
|
||||
const type = resource.request.slice(resource.request.indexOf('/') + 1);
|
||||
|
||||
resource.request = [
|
||||
// the "val-loader" is used to execute create_ui_exports_module
|
||||
// and use its return value as the source for the module in the
|
||||
// bundle. This allows us to bypass writing to the file system
|
||||
require.resolve('val-loader'), '!', require.resolve('./create_ui_exports_module'), '?',
|
||||
// this JSON is parsed by create_ui_exports_module and determines
|
||||
// what require() calls it will execute within the bundle
|
||||
JSON.stringify({ type, modules: extensions[type] || [] })].join('');
|
||||
}), ...this.uiBundles.getWebpackPluginProviders().map(provider => provider(_webpack2.default))],
|
||||
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.less$/,
|
||||
use: [...getStyleLoaderExtractor(), ...getStyleLoaders(['less-loader'], maybeAddCacheLoader('less', []))]
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
use: [...getStyleLoaderExtractor(), ...getStyleLoaders([], maybeAddCacheLoader('css', []))]
|
||||
}, {
|
||||
test: /\.(html|tmpl)$/,
|
||||
loader: 'raw-loader'
|
||||
}, {
|
||||
test: /\.(png|jpg|gif|jpeg)$/,
|
||||
loader: ['url-loader']
|
||||
}, {
|
||||
test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/,
|
||||
loader: 'file-loader'
|
||||
}, {
|
||||
resource: createSourceFileResourceSelector(/\.js$/),
|
||||
use: maybeAddCacheLoader('babel', [{
|
||||
loader: 'thread-loader',
|
||||
options: this.getThreadLoaderPoolConfig()
|
||||
}, {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
babelrc: false,
|
||||
presets: [BABEL_PRESET_PATH]
|
||||
}
|
||||
}])
|
||||
}, ...this.uiBundles.getPostLoaders().map(loader => _extends({
|
||||
enforce: 'post'
|
||||
}, loader))],
|
||||
noParse: this.uiBundles.getWebpackNoParseRules()
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js', '.json'],
|
||||
mainFields: ['browser', 'browserify', 'main'],
|
||||
modules: ['webpackShims', (0, _utils.fromRoot)('webpackShims'), 'node_modules', (0, _utils.fromRoot)('node_modules')],
|
||||
alias: this.uiBundles.getAliases()
|
||||
},
|
||||
|
||||
performance: {
|
||||
// NOTE: we are disabling this as those hints
|
||||
// are more tailored for the final bundles result
|
||||
// and not for the webpack compilations performance itself
|
||||
hints: false
|
||||
}
|
||||
};
|
||||
|
||||
// when running from the distributable define an environment variable we can use
|
||||
// to exclude chunks of code, modules, etc.
|
||||
const isDistributableConfig = {
|
||||
plugins: [new _webpack2.default.DefinePlugin({
|
||||
'process.env': {
|
||||
'IS_KIBANA_DISTRIBUTABLE': `"true"`
|
||||
}
|
||||
})]
|
||||
};
|
||||
|
||||
// when running from source transpile TypeScript automatically
|
||||
const getSourceConfig = () => {
|
||||
// dev/typescript is deleted from the distributable, so only require it if we actually need the source config
|
||||
const { Project } = require('../dev/typescript');
|
||||
const browserProject = new Project((0, _utils.fromRoot)('tsconfig.browser.json'));
|
||||
|
||||
return {
|
||||
module: {
|
||||
rules: [{
|
||||
resource: createSourceFileResourceSelector(/\.tsx?$/),
|
||||
use: maybeAddCacheLoader('typescript', [{
|
||||
loader: 'thread-loader',
|
||||
options: this.getThreadLoaderPoolConfig()
|
||||
}, {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
happyPackMode: true,
|
||||
transpileOnly: true,
|
||||
experimentalWatchApi: true,
|
||||
onlyCompileBundledFiles: true,
|
||||
configFile: (0, _utils.fromRoot)('tsconfig.json'),
|
||||
compilerOptions: _extends({}, browserProject.config.compilerOptions, {
|
||||
sourceMap: Boolean(this.sourceMaps)
|
||||
})
|
||||
}
|
||||
}])
|
||||
}]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx']
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// We need to add react-addons (and a few other bits) for enzyme to work.
|
||||
// https://github.com/airbnb/enzyme/blob/master/docs/guides/webpack.md
|
||||
const supportEnzymeConfig = {
|
||||
externals: {
|
||||
'mocha': 'mocha',
|
||||
'react/lib/ExecutionEnvironment': true,
|
||||
'react/addons': true,
|
||||
'react/lib/ReactContext': true
|
||||
}
|
||||
};
|
||||
|
||||
const watchingConfig = {
|
||||
plugins: [new _webpack2.default.WatchIgnorePlugin([
|
||||
// When our bundle entry files are fresh they cause webpack
|
||||
// to think they might have changed since the watcher was
|
||||
// initialized, which triggers a second compilation on startup.
|
||||
// Since we can't reliably update these files anyway, we can
|
||||
// just ignore them in the watcher and prevent the extra compilation
|
||||
/bundles[\/\\].+\.entry\.js/])]
|
||||
};
|
||||
|
||||
// in production we set the process.env.NODE_ENV and run
|
||||
// the terser minimizer over our bundles
|
||||
const productionConfig = {
|
||||
mode: 'production',
|
||||
optimization: {
|
||||
minimizer: [new _terserWebpackPlugin2.default({
|
||||
parallel: true,
|
||||
sourceMap: false,
|
||||
terserOptions: {
|
||||
compress: false,
|
||||
mangle: false
|
||||
}
|
||||
})]
|
||||
}
|
||||
};
|
||||
|
||||
return (0, _webpackMerge2.default)(commonConfig, _utils.IS_KIBANA_DISTRIBUTABLE ? isDistributableConfig : getSourceConfig(), this.uiBundles.isDevMode() ? (0, _webpackMerge2.default)(watchingConfig, supportEnzymeConfig) : productionConfig);
|
||||
}
|
||||
|
||||
isFailure(stats) {
|
||||
if (stats.hasErrors()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { warnings } = stats.toJson({ all: false, warnings: true });
|
||||
|
||||
// 1 - when typescript doesn't do a full type check, as we have the ts-loader
|
||||
// configured here, it does not have enough information to determine
|
||||
// whether an imported name is a type or not, so when the name is then
|
||||
// exported, typescript has no choice but to emit the export. Fortunately,
|
||||
// the extraneous export should not be harmful, so we just suppress these warnings
|
||||
// https://github.com/TypeStrong/ts-loader#transpileonly-boolean-defaultfalse
|
||||
//
|
||||
// 2 - Mini Css Extract plugin tracks the order for each css import we have
|
||||
// through the project (and it's successive imports) since version 0.4.2.
|
||||
// In case we have the same imports more than one time with different
|
||||
// sequences, this plugin will throw a warning. This should not be harmful,
|
||||
// but the an issue was opened and can be followed on:
|
||||
// https://github.com/webpack-contrib/mini-css-extract-plugin/issues/250#issuecomment-415345126
|
||||
const filteredWarnings = _Stats2.default.filterWarnings(warnings, STATS_WARNINGS_FILTER);
|
||||
|
||||
return filteredWarnings.length > 0;
|
||||
}
|
||||
|
||||
failedStatsToError(stats) {
|
||||
const details = stats.toString((0, _lodash.defaults)({ colors: true, warningsFilter: STATS_WARNINGS_FILTER }, _Stats2.default.presetToOptions('minimal')));
|
||||
|
||||
return _boom2.default.internal(`Optimizations failure.\n${details.split('\n').join('\n ')}\n`, stats.toJson((0, _lodash.defaults)(_extends({
|
||||
warningsFilter: STATS_WARNINGS_FILTER
|
||||
}, _Stats2.default.presetToOptions('detailed')))));
|
||||
}
|
||||
}
|
||||
exports.default = BaseOptimizer;
|
||||
module.exports = exports['default'];
|
||||
Referencia en una nueva incidencia
Block a user