Files
galaxy/client/webpack.config.js
T

284 lines
10 KiB
JavaScript

/* eslint-env node */
const webpack = require("webpack");
const path = require("path");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const DuplicatePackageCheckerPlugin = require("@cerner/duplicate-package-checker-webpack-plugin");
const { DumpMetaPlugin } = require("dumpmeta-webpack-plugin");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const scriptsBase = path.join(__dirname, "src");
const testsBase = path.join(__dirname, "tests");
const libsBase = path.join(scriptsBase, "libs");
const styleBase = path.join(scriptsBase, "style");
const modulesExcludedFromLibs = [
"jspdf",
"canvg",
"prismjs",
"html2canvas",
"handsontable",
"pikaday",
"moment",
"elkjs",
"@citation-js",
"citeproc",
].join("|");
const buildDate = new Date();
module.exports = (env = {}, argv = {}) => {
// environment name based on -d, -p, webpack flag
const targetEnv = process.env.NODE_ENV == "production" || argv.mode == "production" ? "production" : "development";
let minimizations = {};
if (targetEnv == "production") {
minimizations = {
minimize: true,
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
};
} else {
minimizations = {
minimize: false,
};
}
const buildconfig = {
mode: targetEnv,
entry: {
analysis: ["polyfills", "bundleEntries", "entry/analysis"],
generic: ["polyfills", "bundleEntries", "entry/generic"],
},
output: {
path: path.join(__dirname, "dist"),
filename: "[name].bundled.js",
clean: true,
},
resolve: {
plugins: [new TsconfigPathsPlugin({ extensions: [".ts", ".js", ".json", ".vue", ".scss"] })],
extensions: [".ts", ".js", ".json", ".vue", ".scss"],
modules: [scriptsBase, "node_modules", styleBase, testsBase],
fallback: {
timers: require.resolve("timers-browserify"),
stream: require.resolve("stream-browserify"),
"process/browser": require.resolve("process/browser"),
querystring: require.resolve("querystring-es3"),
util: require.resolve("util/"),
assert: require.resolve("assert/"),
},
alias: {
vue$: path.resolve(__dirname, "node_modules/vue/dist/vue.esm.js"),
jquery$: `${libsBase}/jquery.custom.js`,
jqueryVendor$: `${libsBase}/jquery/jquery.js`,
storemodern$: "store/dist/store.modern.js",
"popper.js": path.resolve(__dirname, "node_modules/popper.js/"),
underscore: path.resolve(__dirname, "node_modules/underscore"),
// client-side application config
config$: path.join(scriptsBase, "config", targetEnv) + ".js",
},
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: "base",
chunks: "all",
test: (m) => m.constructor.name == "CssModule",
priority: -5,
},
libs: {
name: "libs",
test: new RegExp(`node_modules[\\/](?!(${modulesExcludedFromLibs})[\\/])|galaxy/scripts/libs`),
chunks: "all",
priority: -10,
},
},
},
...minimizations,
},
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: "ts-loader",
options: {
configFile: "tsconfig.webpack.json",
appendTsSuffixTo: [/\.vue$/],
},
},
{
test: /\.mjs$/,
include: /node_modules/,
type: "javascript/auto",
},
{
test: `${libsBase}/jquery.custom.js`,
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
{
test: require.resolve("underscore"),
use: [
{
loader: "expose-loader",
options: {
exposes: {
globalName: ["underscore", "_"],
},
},
},
],
},
// Alternative to setting window.bundleEntries
// Just import "bundleEntries" in any endpoint that needs
// access to these globals, or even-better, make
// more endpoints and skip the global altogether
{
test: `${scriptsBase}/bundleEntries`,
use: [
{
loader: "expose-loader",
options: {
exposes: "bundleEntries",
},
},
],
},
{
test: `${scriptsBase}/onload/loadConfig.js`,
use: [
{
loader: "expose-loader",
options: { exposes: "config" },
},
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {},
},
{
loader: "css-loader",
options: { sourceMap: true },
},
{
loader: "postcss-loader",
},
{
loader: "sass-loader",
options: {
sourceMap: true,
sassOptions: {
quietDeps: true,
includePaths: [
path.join(styleBase, "scss"),
path.resolve(__dirname, "./node_modules"),
],
},
},
},
],
},
{
test: /\.(txt|tmpl)$/,
loader: "raw-loader",
},
{
test: /\.ya?ml$/,
use: "yaml-loader",
},
],
},
resolveLoader: {
alias: {
// since we support both requirejs i18n and non-requirejs and both use a similar syntax,
// use an alias so we can just use one file
i18n: "amdi18n-loader",
},
},
plugins: [
// this plugin allows using the following keys/globals in scripts (w/o req'ing them first)
// and webpack will automagically require them in the bundle for you
new webpack.ProvidePlugin({
$: `${libsBase}/jquery.custom.js`,
jQuery: `${libsBase}/jquery.custom.js`,
"window.jQuery": `${libsBase}/jquery.custom.js`,
_: "underscore",
Backbone: "backbone",
Galaxy: ["app", "monitor"],
Buffer: ["buffer", "Buffer"],
process: "process/browser",
}),
new webpack.DefinePlugin({
__targetEnv__: JSON.stringify(targetEnv),
__buildTimestamp__: JSON.stringify(buildDate.toISOString()),
__license__: JSON.stringify(require("./package.json").license),
}),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "[name].css",
}),
new DuplicatePackageCheckerPlugin(),
new DumpMetaPlugin({
filename: path.join(__dirname, "../lib/galaxy/web/framework/meta.json"),
prepare: (stats) => ({
// add any other information you need to dump
hash: stats.hash,
epoch: Date.parse(buildDate),
}),
}),
],
devServer: {
client: {
overlay: {
errors: true,
warnings: false,
},
webSocketURL: {
port: process.env.GITPOD_WORKSPACE_ID ? 443 : undefined,
},
},
allowedHosts: process.env.GITPOD_WORKSPACE_ID ? "all" : "auto",
devMiddleware: {
publicPath: "/static/dist",
writeToDisk: true,
},
hot: true,
port: process.env.WEBPACK_PORT || 8081,
host: "0.0.0.0",
// proxy *everything* to the galaxy server.
// someday, when we have a fully API-driven independent client, this
// can be a more limited set -- e.g. `/api`, `/auth`
proxy: {
"**": {
// We explicitly use ipv4 loopback instead of localhost to
// avoid ipv6/ipv4 resolution order issues; this should
// align with Galaxy's default.
target: process.env.GALAXY_URL || "http://127.0.0.1:8080",
secure: process.env.CHANGE_ORIGIN ? !process.env.CHANGE_ORIGIN : true,
changeOrigin: !!process.env.CHANGE_ORIGIN,
logLevel: "debug",
},
},
},
};
if (process.env.GXY_BUILD_SOURCEMAPS) {
buildconfig.devtool = "source-map";
}
return buildconfig;
};