mstr-viz
Version:
A new dev tool for creating custom visualizations
200 lines (192 loc) • 5.7 kB
JavaScript
const path = require('path');
const fs = require('fs-extra');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const CreateFileWebpack = require('create-file-webpack');
const space = require('../utils/space');
const getFileExtension = require('./getFileExtension');
module.exports = env => {
const {
pluginName, mode, icon, formatPanelSrcBuildEntry, shouldBuildReact,
} = env;
const projectRoot = space.recover(env.projectRoot);
const distDir = space.recover(env.distDir);
const oldJSDir = 'javascript/mojo/js/source/';
const reactFmtPanelDestDirOld = './formatPanelConfig/';
const reactFmtPanelDestDirNew = './formatPanelBundles/';
const targetBrowsers = [
'last 20 chrome versions',
'last 20 firefox versions',
'safari >= 7',
'edge >= 12',
'ie >= 11',
'not dead',
];
const entryPaths = {
plugin: `./src/${pluginName}`,
dropZones: `./src/${pluginName}DropZones`,
editorModel: `./src/${pluginName}EditorModel`,
};
const common = {
context: projectRoot,
mode,
entry: {
viz: {
import: entryPaths.plugin + getFileExtension(path.join(projectRoot, entryPaths.plugin)),
filename: `${oldJSDir}${pluginName}.js`,
},
dz: {
import: entryPaths.dropZones
+ getFileExtension(path.join(projectRoot, entryPaths.dropZones)),
filename: `${oldJSDir}${pluginName}DropZones.js`,
},
edtMdl: {
import: entryPaths.editorModel
+ getFileExtension(path.join(projectRoot, entryPaths.editorModel)),
filename: `${oldJSDir}${pluginName}EditorModel.js`,
},
},
output: {
path: path.resolve(distDir),
},
resolveLoader: {
modules: [
'node_modules',
// mstr-viz node_modules
path.resolve(__dirname, '../../node_modules'),
path.resolve(__dirname, 'loaders'),
],
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '...'],
},
module: {
rules: [
{
test: /\.(js|jsx|tsx|ts)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-react',
{
development: mode === 'development',
},
],
[
'@babel/preset-env',
{
targets: targetBrowsers,
},
],
],
plugins: [
[
'@babel/plugin-proposal-decorators',
{ decoratorsBeforeExport: true },
],
['@babel/plugin-transform-class-properties', { loose: true }],
['@babel/plugin-transform-private-property-in-object', { loose: true }],
['@babel/plugin-transform-private-methods', { loose: true }],
],
},
},
{ loader: 'plugin-namespace-loader', options: { pluginName } },
],
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: ['ts-loader'],
},
{
test: /\.less$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
},
}, 'css-loader', 'less-loader'],
},
// Icon styles need to be inserted into vis.less first.
// So this rule must be placed after the common less rule
{
test: /vis\.less$/,
use: [
{ loader: 'icon-loader.js', options: { icon, name: pluginName } },
],
},
{
test: /\.(svg|png|jpe?g|gif)$/,
type: 'asset/resource',
generator: {
filename: 'style/images/[hash][ext]',
},
},
{
test: new RegExp(`${pluginName}\\.(js|ts|jsx|tsx)$`),
use: [{ loader: 'style-dep-loader.js' }],
},
],
},
optimization: {
minimizer: ['...', new CssMinimizerPlugin()],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
},
},
},
plugins: [
new MiniCssExtractPlugin({ filename: 'style/global.css' }),
new CreateFileWebpack({
path: path.join(distDir, 'style'),
fileName: 'Html5ViPage.css',
content: '/* THIS FILE IS ONLY A PLACEHOLDER AND USELESS */',
}),
],
};
const reactFmtPanelBuildEntry = path.join(projectRoot, formatPanelSrcBuildEntry);
if (shouldBuildReact === 'true' && fs.existsSync(reactFmtPanelBuildEntry)) {
common.entry.fmtPanel = {
import: reactFmtPanelBuildEntry,
filename: `${reactFmtPanelDestDirOld}config.js`,
library: {
type: 'umd',
umdNamedDefine: false,
},
};
common.entry.fmtPanelSafe = {
import: reactFmtPanelBuildEntry,
filename: `${reactFmtPanelDestDirNew}format.js`,
library: {
type: 'umd',
umdNamedDefine: false,
},
};
}
if (mode === 'development') {
return {
...common,
devtool: 'eval-cheap-module-source-map',
watch: true,
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 2000,
},
stats: {
errorDetails: true,
},
};
}
return common;
};