xref: /openbmc/webui-vue/vue.config.js (revision d36ac8a8be8636ddd0e64ce005d507b21bcdeb00)
1const CompressionPlugin = require('compression-webpack-plugin');
2const webpack = require('webpack');
3const LimitChunkCountPlugin = webpack.optimize.LimitChunkCountPlugin;
4
5module.exports = {
6  css: {
7    loaderOptions: {
8      sass: {
9        additionalData: (() => {
10          const envName = process.env.VUE_APP_ENV_NAME;
11          const hasCustomStyles = process.env.CUSTOM_STYLES === 'true';
12          if (hasCustomStyles && envName !== undefined) {
13            return `
14              @import "@/assets/styles/bmc/helpers";
15              @import "@/env/assets/styles/_${envName}";
16              @import "@/assets/styles/bootstrap/_helpers";
17            `;
18          } else {
19            return `
20              @import "@/assets/styles/bmc/helpers";
21              @import "@/assets/styles/bootstrap/_helpers";
22            `;
23          }
24        })(), // immediately invoked function expression (IIFE)
25      },
26      scss: {
27        additionalData: (() => {
28          const envName = process.env.VUE_APP_ENV_NAME;
29          const hasCustomStyles = process.env.CUSTOM_STYLES === 'true';
30          if (hasCustomStyles && envName !== undefined) {
31            return `
32              @import "@/assets/styles/bmc/helpers";
33              @import "@/env/assets/styles/_${envName}";
34              @import "@/assets/styles/bootstrap/_helpers";
35            `;
36          } else {
37            return `
38              @import "@/assets/styles/bmc/helpers";
39              @import "@/assets/styles/bootstrap/_helpers";
40            `;
41          }
42        })(),
43      },
44    },
45  },
46  devServer: {
47    // Set DEV_HTTPS=true to run with HTTPS (helpful for testing secure-only features or with a signed cert)
48    // ref https://webpack.js.org/configuration/dev-server/#devserverserver
49    server:
50      process.env.DEV_HTTPS === 'true' ? { type: 'https' } : { type: 'http' },
51    proxy: {
52      '/': {
53        target: process.env.BASE_URL,
54        onProxyRes: (proxyRes) => {
55          delete proxyRes.headers['strict-transport-security'];
56        },
57      },
58    },
59    port: 8000,
60  },
61  productionSourceMap: false,
62  chainWebpack: (config) => {
63    config.module
64      .rule('vue')
65      .use('vue-svg-inline-loader')
66      .loader('vue-svg-inline-loader');
67    config.module
68      .rule('ico')
69      .test(/\.ico$/)
70      .use('file-loader')
71      .loader('file-loader')
72      .options({
73        name: '[name].[contenthash:8].[ext]',
74      });
75    config.plugins.delete('preload');
76    if (process.env.NODE_ENV === 'production') {
77      config.plugin('html').tap((options) => {
78        options[0].filename = 'index.[hash:8].html';
79        return options;
80      });
81    }
82  },
83  configureWebpack: (config) => {
84    config.plugins.push(
85      new LimitChunkCountPlugin({
86        maxChunks: 1,
87      }),
88    );
89    config.optimization.splitChunks = {
90      cacheGroups: {
91        default: false,
92      },
93    };
94    const crypto = require('crypto');
95    const crypto_orig_createHash = crypto.createHash;
96    crypto.createHash = (algorithm) =>
97      crypto_orig_createHash(algorithm == 'md4' ? 'sha256' : algorithm);
98
99    const envName = process.env.VUE_APP_ENV_NAME;
100    const hasCustomStore = process.env.CUSTOM_STORE === 'true';
101    const hasCustomRouter = process.env.CUSTOM_ROUTER === 'true';
102    const hasCustomAppNav = process.env.CUSTOM_APP_NAV === 'true';
103
104    if (envName !== undefined) {
105      if (hasCustomStore) {
106        // If env has custom store, resolve all store modules. Currently found
107        // in src/router/index.js src/store/api.js and src/main.js
108        config.resolve.alias['./store$'] = `@/env/store/${envName}.js`;
109        config.resolve.alias['../store$'] = `@/env/store/${envName}.js`;
110      }
111      if (hasCustomRouter) {
112        // If env has custom router, resolve routes in src/router/index.js
113        config.resolve.alias['./routes$'] = `@/env/router/${envName}.js`;
114      }
115      if (hasCustomAppNav) {
116        // If env has custom AppNavigation, resolve AppNavigationMixin module in src/components/AppNavigation/AppNavigation.vue
117        config.resolve.alias['./AppNavigationMixin$'] =
118          `@/env/components/AppNavigation/${envName}.js`;
119      }
120    }
121
122    if (process.env.NODE_ENV === 'production') {
123      config.plugins.push(
124        new CompressionPlugin({
125          deleteOriginalAssets: true,
126        }),
127      );
128    }
129
130    config.performance = {
131      hints: 'warning',
132      maxEntrypointSize: 512000,
133      maxAssetSize: 512000,
134    };
135
136    config.optimization.runtimeChunk = false;
137
138    // Define Vue 3 compile-time feature flags
139    // These flags must be explicitly defined to avoid Vue warnings and optimize bundle size
140    config.plugins.push(
141      new webpack.DefinePlugin({
142        // Enable Options API support (required - this codebase uses Options API extensively)
143        // Setting to true includes Options API in the bundle (~3kb gzipped)
144        // Cannot be disabled until full migration to Composition API
145        __VUE_OPTIONS_API__: JSON.stringify(true),
146
147        // Disable Vue Devtools in production builds for security and performance
148        // Devtools automatically enabled in development mode regardless of this flag
149        __VUE_PROD_DEVTOOLS__: JSON.stringify(false),
150
151        // Disable detailed hydration mismatch warnings in production
152        // This is a SPA (not SSR), so hydration warnings don't apply
153        // Reduces bundle size and eliminates unnecessary runtime checks
154        __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(false),
155
156        // Expose session storage toggle to client code
157        'process.env.STORE_SESSION': JSON.stringify(
158          process.env.STORE_SESSION || '',
159        ),
160        'process.env.VUE_APP_STORE_SESSION': JSON.stringify(
161          process.env.VUE_APP_STORE_SESSION || '',
162        ),
163      }),
164    );
165  },
166  pluginOptions: {
167    i18n: {
168      localeDir: 'locales',
169      enableInSFC: true,
170    },
171  },
172};
173