Build: optimize frontend build configs to improve superset-ui-plugin dev experience (#9326)

* Upgrade webpack, babel and React

* Upgrade all Babel related packages

Also remove babel-plugin-css-modules-transform that is not in use.

* Remvoe tslib as dependency

* Remove unnecesary packages
This commit is contained in:
Jianchao Yang
2020-03-19 14:57:39 -07:00
committed by GitHub
parent ff703cf01b
commit c4b53a7d42
16 changed files with 13875 additions and 5473 deletions

View File

@@ -18,7 +18,6 @@
* under the License.
*/
const fs = require('fs');
const os = require('os');
const path = require('path');
const webpack = require('webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
@@ -32,6 +31,7 @@ const TerserPlugin = require('terser-webpack-plugin');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const parsedArgs = require('yargs').argv;
const packageConfig = require('./package.json');
// input dir
const APP_DIR = path.resolve(__dirname, './');
@@ -84,6 +84,7 @@ const plugins = [
// runs type checking on a separate process to speed up the build
new ForkTsCheckerWebpackPlugin({
eslint: true,
checkSyntacticErrors: true,
}),
@@ -96,10 +97,7 @@ const plugins = [
{ copyUnmodified: true },
),
];
if (isDevMode) {
// Enable hot module replacement
plugins.push(new webpack.HotModuleReplacementPlugin());
} else {
if (!isDevMode) {
// text loading (webpack 4+)
plugins.push(
new MiniCssExtractPlugin({
@@ -110,45 +108,29 @@ if (isDevMode) {
plugins.push(new OptimizeCSSAssetsPlugin());
}
const BABEL_JAVASCRIPT_OPTIONS = {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
loose: true,
shippedProposals: true,
modules: false,
targets: false,
},
],
'@babel/preset-react',
],
plugins: [
'lodash',
'react-hot-loader/babel',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-syntax-dynamic-import',
],
};
const BABEL_TYPESCRIPT_OPTIONS = {
presets: BABEL_JAVASCRIPT_OPTIONS.presets.concat([
'@babel/preset-typescript',
]),
plugins: BABEL_JAVASCRIPT_OPTIONS.plugins.concat([
'babel-plugin-typescript-to-proptypes',
]),
};
const PREAMBLE = ['babel-polyfill', path.join(APP_DIR, '/src/preamble.js')];
const PREAMBLE = [path.join(APP_DIR, '/src/preamble.js')];
if (isDevMode) {
// A Superset webpage normally includes two JS bundles in dev, `theme.js` and
// the main entrypoint. Only the main entry should have the dev server client,
// otherwise the websocket client will initialize twice, creating two sockets.
// Ref: https://github.com/gaearon/react-hot-loader/issues/141
PREAMBLE.unshift(
`webpack-dev-server/client?http://localhost:${devserverPort}`,
);
}
function addPreamble(entry) {
return PREAMBLE.concat([path.join(APP_DIR, entry)]);
}
const babelLoader = {
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false,
},
};
const config = {
node: {
fs: 'empty',
@@ -165,6 +147,13 @@ const config = {
showSavedQuery: [path.join(APP_DIR, '/src/showSavedQuery/index.jsx')],
},
output,
stats: 'minimal',
performance: {
assetFilter(assetFilename) {
// don't throw size limit warning on geojson and font files
return !/\.(map|geojson|woff2)$/.test(assetFilename);
},
},
optimization: {
splitChunks: {
chunks: 'all',
@@ -174,7 +163,7 @@ const config = {
default: false,
major: {
name: 'vendors-major',
test: /[\\/]node_modules\/(brace|react[-]dom|@superset[-]ui\/translation)[\\/]/,
test: /\/node_modules\/(brace|react|react-dom|@superset-ui\/translation|webpack.*|@babel.*)\//,
},
},
},
@@ -182,6 +171,7 @@ const config = {
resolve: {
alias: {
src: path.resolve(APP_DIR, './src'),
'react-dom': '@hot-loader/react-dom',
},
extensions: ['.ts', '.tsx', '.js', '.jsx'],
symlinks: false,
@@ -199,57 +189,29 @@ const config = {
{
test: /\.tsx?$/,
use: [
{ loader: 'cache-loader' },
{
loader: 'thread-loader',
options: {
// there should be 1 cpu for the fork-ts-checker-webpack-plugin
workers: os.cpus().length - 1,
},
},
'thread-loader',
babelLoader,
{
loader: 'ts-loader',
options: {
// transpile only in happyPack mode
// type checking is done via fork-ts-checker-webpack-plugin
happyPackMode: true,
transpileOnly: true,
},
},
],
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
include: APP_DIR,
loader: 'babel-loader',
},
{
// handle symlinked modules
// for debugging @superset-ui packages via npm link
test: /\.jsx?$/,
include: /node_modules\/[@]superset[-]ui.+\/src/,
use: [
{
loader: 'babel-loader',
options: BABEL_JAVASCRIPT_OPTIONS,
},
],
},
{
// handle symlinked modules
// for debugging @superset-ui packages via npm link
test: /\.tsx?$/,
include: /node_modules\/[@]superset[-]ui.+\/src/,
use: [
{
loader: 'babel-loader',
options: BABEL_TYPESCRIPT_OPTIONS,
},
],
// include source code for plugins, but exclude node_modules within them
exclude: [/superset-ui.*\/node_modules\/.*/],
include: [new RegExp(`${APP_DIR}/src`), /superset-ui.*\/src/],
use: [babelLoader],
},
{
test: /\.css$/,
include: [APP_DIR, /superset[-]ui.+\/src/],
include: [APP_DIR, /superset-ui.+\/src/],
use: [
isDevMode ? 'style-loader' : MiniCssExtractPlugin.loader,
{
@@ -331,8 +293,7 @@ function loadProxyConfig() {
}
if (isDevMode) {
config.devtool = 'cheap-module-eval-source-map';
config.devtool = 'eval-cheap-module-source-map';
config.devServer = {
before() {
loadProxyConfig();
@@ -341,6 +302,8 @@ if (isDevMode) {
},
historyApiFallback: true,
hot: true,
injectClient: false,
injectHot: true,
inline: true,
stats: 'minimal',
overlay: true,
@@ -355,6 +318,24 @@ if (isDevMode) {
],
contentBase: path.join(process.cwd(), '../static/assets'),
};
// find all the symlinked plugins and use their source code for imports
let hasSymlink = false;
for (const [pkg, version] of Object.entries(packageConfig.dependencies)) {
const srcPath = `./node_modules/${pkg}/src`;
if (/superset-ui/.test(pkg) && fs.existsSync(srcPath)) {
console.log(
`[Superset Plugin] Use symlink source for ${pkg} @ ${version}`,
);
// only allow exact match so imports like `@superset-ui/plugin-name/lib`
// and `@superset-ui/plugin-name/esm` can still work.
config.resolve.alias[`${pkg}$`] = `${pkg}/src`;
hasSymlink = true;
}
}
if (hasSymlink) {
console.log(''); // pure cosmetic new line
}
} else {
config.optimization.minimizer = [
new TerserPlugin({