@genesislcap/webpack-builder 14.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +26 -0
  2. package/cert/localhost.crt +25 -0
  3. package/cert/localhost.key +28 -0
  4. package/dist/cert/localhost.crt +25 -0
  5. package/dist/cert/localhost.key +28 -0
  6. package/dist/config/configFactory.d.ts +7 -0
  7. package/dist/config/configFactory.d.ts.map +1 -0
  8. package/dist/config/configFactory.js +51 -0
  9. package/dist/config/devServers.d.ts +35 -0
  10. package/dist/config/devServers.d.ts.map +1 -0
  11. package/dist/config/devServers.js +67 -0
  12. package/dist/config/postcss.config.d.ts +2 -0
  13. package/dist/config/postcss.config.d.ts.map +1 -0
  14. package/dist/config/postcss.config.js +8 -0
  15. package/dist/config/utils.d.ts +20 -0
  16. package/dist/config/utils.d.ts.map +1 -0
  17. package/dist/config/utils.js +77 -0
  18. package/dist/config/webpack.common.d.ts +68 -0
  19. package/dist/config/webpack.common.d.ts.map +1 -0
  20. package/dist/config/webpack.common.js +113 -0
  21. package/dist/config/webpack.dev.d.ts +68 -0
  22. package/dist/config/webpack.dev.d.ts.map +1 -0
  23. package/dist/config/webpack.dev.js +31 -0
  24. package/dist/config/webpack.prod.d.ts +68 -0
  25. package/dist/config/webpack.prod.d.ts.map +1 -0
  26. package/dist/config/webpack.prod.js +43 -0
  27. package/dist/index.d.ts +4 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +26 -0
  30. package/dist/public/favicon.ico +0 -0
  31. package/dist/public/index.ejs +23 -0
  32. package/dist/public/info.ejs +13 -0
  33. package/dist/public/serve.json +3 -0
  34. package/dist/rules/fileRules.d.ts +17 -0
  35. package/dist/rules/fileRules.d.ts.map +1 -0
  36. package/dist/rules/fileRules.js +24 -0
  37. package/dist/rules/scriptRules.d.ts +14 -0
  38. package/dist/rules/scriptRules.d.ts.map +1 -0
  39. package/dist/rules/scriptRules.js +19 -0
  40. package/dist/rules/styleRules.d.ts +54 -0
  41. package/dist/rules/styleRules.d.ts.map +1 -0
  42. package/dist/rules/styleRules.js +53 -0
  43. package/license.txt +46 -0
  44. package/package.json +56 -0
  45. package/public/cert/README.md +17 -0
  46. package/public/cert/localhost.crt +25 -0
  47. package/public/cert/localhost.key +28 -0
  48. package/public/favicon.ico +0 -0
  49. package/public/index.ejs +23 -0
  50. package/public/info.ejs +13 -0
  51. package/public/serve.json +3 -0
  52. package/src/config/configFactory.js +56 -0
  53. package/src/config/devServers.js +73 -0
  54. package/src/config/postcss.config.js +8 -0
  55. package/src/config/utils.js +99 -0
  56. package/src/config/webpack.common.js +117 -0
  57. package/src/config/webpack.dev.js +32 -0
  58. package/src/config/webpack.prod.js +47 -0
  59. package/src/index.ts +29 -0
  60. package/src/rules/fileRules.js +26 -0
  61. package/src/rules/scriptRules.js +21 -0
  62. package/src/rules/styleRules.js +60 -0
  63. package/tsconfig.json +18 -0
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDeF4UmMyoH3SHn
3
+ njIOY6WDVCVVw45KViOXM+957zc7VtBgGYu75/rbNooXj9unmOHSO12sp0+yV6pK
4
+ mmycRc+THILz8nvSldH6EwX018tRoOQJ7BIK54tczZpiZ2uswdGG5mjAHhX3Dkfr
5
+ LoRbYtd0eaabLYINTIMxVrGiWDUn84gaso+xPQkwUVpjyiK883bEJSwa4hri64D3
6
+ rCHSn2HxIMubRySzYKUFcExks4m5J2XZklPk/XWu4X5ojrXCqtRNyTzMCE4cZofU
7
+ Ag5arCofuassGoFZZRtjmlEMSXxq6uSIXuel8xv9mXmbmZfB/jTN6EcNnzKLFtYN
8
+ KVRJGs0dAgMBAAECggEAUrGLQEf4tGjgAO/kT3tG23lvVVm1F3SvV9NcrZgmho+y
9
+ krWwU8zymMDb9h34eZTxMGguXuUFRbBildid7CoKOgp5r/9vn19tiaGfrCTVbZVs
10
+ k001Ap5oQ6vCejVr4C1iqMoN4srQ/uZwXN87JRPOiW3qXQk6zVzZ1HslNP+G+1J+
11
+ Q5FeaLei+nZzY+Aug8u/l1+FaE09m8xt7Rghn1sEg7IFdP+7pImkrzuykT0ceE+g
12
+ XkQNk2YcChGuF3pV0fyXzWwwR5rYoxEtbNrc42pBTEiBtKqh6GjHjJCkqMeVQvuy
13
+ d1PMWxyXyu2HqtzddDHVknAFlRy9KSc80AgyQOSAeQKBgQDfuPXBGbJiXewHygyX
14
+ TkEXmGrAxQ8+Gxn8blj6LzALNjjGDiW9CwbxmVWdMbEBE3lUZi92erCYLFZUPXTa
15
+ BdPsE1dki2T2eVWVwK/qoc44IBDCJ3LtjfODNi5OaTBvAUMzI3pYVJS0vwM86ywx
16
+ UF3R54RHGPLdNN0So8k45QDQmwKBgQD+IlWIzigv1SEiEOaqQUoJB0Vfxq2u91eN
17
+ ius5Wj5ONDfNv++mbr3bBuI0Bpg4u7W9i5hJVLE04GtlfjSuOX0QnkbQYu5/NbCH
18
+ Vxw9YUwtOZJlk0kx3H6qpftYgEPwXir7fcuoXFUT7jD+Q5FWvQA76asF9zVnt9RG
19
+ OGoB6FeopwKBgQDP9wZzxyhcakRzhS2pJPQ7M9LgeQ5PRDAmyIjroBvAAFpMOXB5
20
+ R5vf0BKWuk942Zpqi0bJkwk/m89wJWTPGqXCCMSvUSi8OVQGjgS5Tkn9QElzweoC
21
+ y3a23RG0j/GW7oyCKBOdspo9XmZrJY2CFdvwuI7s7FMur+plXl06Bx53ywKBgQDO
22
+ ehjiuRUfn9t2sSKoS7maUkUERwkQcje5cZgiFfcvVO/OBFby82Df1tzshjshRSmp
23
+ IgUN93iuzHOVl4+3yk+Zs+83GlpKEtYlcBoqqKXazL7sNlmu4EYt4gOv6S7J2ci0
24
+ YoWYecRKGCnIPB+WyKKrCvQAOdUzOsGGeAlxGVQ3WwKBgE7fJGLuraf1hHRMuPsS
25
+ ZGnJE93QVWOFCym34lxRWEQ3rKEXMtAhUhq/M6x5sJnv7ePTujyDoPAbAioxLS/L
26
+ GsrvcDc91bwNs7sDTyq//n0ehf2HJMFrbdtIPblxA26dHtX7BmW6eppDhm4OV8zO
27
+ 1vSzX8HjCcx1AkcATKDA9J3e
28
+ -----END PRIVATE KEY-----
Binary file
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title><%= htmlWebpackPlugin.options.title %></title>
7
+ <style>
8
+ html,
9
+ body {
10
+ width: 100%;
11
+ height: 100%;
12
+ padding: 0;
13
+ margin: 0;
14
+ }
15
+ :not(:defined) {
16
+ visibility: hidden;
17
+ }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <<%= htmlWebpackPlugin.options.customElementTagName %>></<%= htmlWebpackPlugin.options.customElementTagName %>>
22
+ </body>
23
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title><%= htmlWebpackPlugin.options.title %></title>
6
+ </head>
7
+ <body>
8
+ <h1><%= htmlWebpackPlugin.options.title %></h1>
9
+ <h3>Module Federation Details</h3>
10
+ <pre><%= htmlWebpackPlugin.options.moduleFederationDetails %></pre>
11
+ Read about <a href="https://webpack.js.org/concepts/module-federation/" target="_blank">Module Federation</a> in Webpack 5.
12
+ </body>
13
+ </html>
@@ -0,0 +1,3 @@
1
+ {
2
+ "rewrites": [ { "source": "/**", "destination": "/index.html" } ]
3
+ }
@@ -0,0 +1,56 @@
1
+ const { existsSync } = require('node:fs');
2
+ const { resolve } = require('node:path');
3
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
4
+ const portfinderSync = require('portfinder-sync');
5
+ const { merge } = require('webpack-merge');
6
+ const { getWebpackMFConfigFragment, federatedIndexExists } = require('./utils');
7
+ const devConfigFactory = require('./webpack.dev');
8
+ const prodConfig = require('./webpack.prod');
9
+
10
+ const getTemplate = () => {
11
+ const templateApp = resolve(process.cwd(), 'public/index.ejs');
12
+ const templateDefault = resolve(__dirname, '../public/index.ejs');
13
+ const template = existsSync(templateApp) ? templateApp : templateDefault;
14
+ console.log(`Using index template: ${template}`);
15
+ return template;
16
+ };
17
+
18
+ /**
19
+ * Webpack config factory
20
+ *
21
+ * @param packageJson The package.json file of the target package.
22
+ * @param mfOptions Module federation options to merged into the base options
23
+ * @param customElementTagName Tag name for insertion in the index.html file, ie. `foundation-xyz`
24
+ * @returns The the port number, webpack config (which can be extended further), and an isProd flag.
25
+ */
26
+ module.exports = (packageJson, mfOptions = {}, customElementTagName) => {
27
+ const port = portfinderSync.getPort(packageJson.config?.PORT || process.env.PORT || 9000);
28
+ const isProd = process.env.NODE_ENV === 'production';
29
+ const envConfig = isProd ? prodConfig() : devConfigFactory(port);
30
+ const federatedIndexPresent = federatedIndexExists();
31
+ const mfConfig = federatedIndexPresent
32
+ ? getWebpackMFConfigFragment(
33
+ packageJson,
34
+ mfOptions,
35
+ customElementTagName ? 'info.html' : 'index.html'
36
+ )
37
+ : {};
38
+ const mergedConfig = merge(envConfig, mfConfig, {
39
+ plugins: [
40
+ ...(customElementTagName || !federatedIndexPresent
41
+ ? [
42
+ new HtmlWebpackPlugin({
43
+ title: `${packageJson.description}`,
44
+ template: getTemplate(),
45
+ customElementTagName,
46
+ }),
47
+ ]
48
+ : []),
49
+ ],
50
+ });
51
+ return {
52
+ port,
53
+ default: mergedConfig,
54
+ isProd,
55
+ };
56
+ };
@@ -0,0 +1,73 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const server = {
5
+ type: process.argv.includes('--https') ? 'https' : 'http',
6
+ };
7
+ if (server.type === 'https') {
8
+ try {
9
+ server.options = {
10
+ cert: fs.readFileSync(path.resolve(__dirname, '../cert/localhost.crt')),
11
+ key: fs.readFileSync(path.resolve(__dirname, '../cert/localhost.key')),
12
+ };
13
+ } catch (err) {
14
+ console.warn(
15
+ 'You may be trying to run the webpack dev server in HTTPS mode without local certificates. Please see @genesislcap/webpack-builder README'
16
+ );
17
+ }
18
+ }
19
+ const convertWsEndpointToHTTP = (endpoint = '', socketExt) =>
20
+ (endpoint.startsWith('ws:')
21
+ ? endpoint.replace('ws:', 'http:')
22
+ : endpoint.startsWith('wss:')
23
+ ? endpoint.replace('wss:', 'https:')
24
+ : endpoint
25
+ ).replace(`/${socketExt}`, '');
26
+
27
+ const devServers = {
28
+ default: (port = process.env.PORT || 9000, host = 'localhost') => {
29
+ const socketExt = process.env.SOCKET_EXT || 'gwf';
30
+ const target = convertWsEndpointToHTTP(process.env.API_HOST, socketExt);
31
+ return {
32
+ open: !process.env.CI,
33
+ historyApiFallback: true,
34
+ allowedHosts: 'all',
35
+ host,
36
+ port,
37
+ server,
38
+ client: {
39
+ overlay: {
40
+ runtimeErrors: false,
41
+ },
42
+ },
43
+ proxy: [
44
+ {
45
+ context: [`/${socketExt}/**`, '/sso/**'],
46
+ target,
47
+ secure: false,
48
+ changeOrigin: true,
49
+ },
50
+ ],
51
+ // disableHostCheck: true,
52
+ // sockHost: 'localhost',
53
+ // sockPort: '8080',
54
+ // https: true,
55
+ headers: {
56
+ 'Access-Control-Allow-Origin': '*',
57
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
58
+ 'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
59
+ },
60
+ static: [
61
+ {
62
+ directory: path.resolve(process.cwd(), './public'),
63
+ publicPath: '/',
64
+ watch: true,
65
+ },
66
+ ],
67
+ };
68
+ },
69
+ };
70
+
71
+ module.exports = {
72
+ devServers,
73
+ };
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ plugins: [
3
+ require('postcss-import'),
4
+ require('postcss-preset-env')({
5
+ browsers: 'last 2 versions',
6
+ }),
7
+ ],
8
+ };
@@ -0,0 +1,99 @@
1
+ const { existsSync } = require('node:fs');
2
+ const { resolve } = require('node:path');
3
+ const DashboardPlugin = require('@module-federation/dashboard-plugin');
4
+ const { camelCase } = require('camel-case');
5
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
6
+ const webpack = require('webpack');
7
+
8
+ const { ModuleFederationPlugin } = webpack.container;
9
+ const remoteEntryFilename = 'remoteEntry.js';
10
+
11
+ const getFederatedPkgName = (pkgName) => {
12
+ try {
13
+ return camelCase(pkgName.split('/').pop());
14
+ } catch (e) {
15
+ return pkgName;
16
+ }
17
+ };
18
+
19
+ /**
20
+ * TODO: Add prod version logic
21
+ */
22
+ const getRemoteEntryUrl = (port, host = 'localhost') =>
23
+ `http://${host}:${port}/${remoteEntryFilename}`;
24
+ const getRemoteEntry = (name, port, host = 'localhost') =>
25
+ `${name}@${getRemoteEntryUrl(port, host)}`;
26
+
27
+ const federatedIndex = './src/index.federated.ts';
28
+
29
+ const resolveFederatedIndex = () => resolve(process.cwd(), federatedIndex);
30
+
31
+ const federatedIndexExists = () => {
32
+ const federatedIndexPath = resolveFederatedIndex();
33
+ return existsSync(federatedIndexPath);
34
+ };
35
+
36
+ /**
37
+ * Webpack module federation config fragment factory
38
+ *
39
+ * @param packageJson The package.json file of the target package.
40
+ * @param mfOptions Module federation options to merged into the base options
41
+ * @param htmlFilename The filename value for the report generated by the html plugin
42
+ * @returns A partial webpack config fragment to be merged into a final webpack config.
43
+ */
44
+ const getWebpackMFConfigFragment = (packageJson, mfOptions = {}, htmlFilename = 'index.html') => {
45
+ const name = getFederatedPkgName(packageJson.name);
46
+ const deps = packageJson.dependencies;
47
+ const { exposes: mfExposes = {}, remotes: mfRemotes = {}, shared: mfShared = {} } = mfOptions;
48
+
49
+ const exposes = {
50
+ './index': federatedIndex,
51
+ ...mfExposes,
52
+ };
53
+
54
+ const remotes = {
55
+ ...mfRemotes,
56
+ };
57
+
58
+ const shared = {
59
+ ...deps,
60
+ ...mfShared,
61
+ };
62
+
63
+ const moduleFederationOptions = {
64
+ name,
65
+ filename: remoteEntryFilename,
66
+ remotes,
67
+ exposes,
68
+ shared,
69
+ };
70
+
71
+ return {
72
+ entry: resolveFederatedIndex(),
73
+ plugins: [
74
+ new ModuleFederationPlugin(moduleFederationOptions),
75
+ new DashboardPlugin({
76
+ dashboardURL: 'http://localhost:3000/api/update',
77
+ publishVersion: '1.0.0',
78
+ }),
79
+ new HtmlWebpackPlugin({
80
+ title: `${packageJson.description} (Federated)`,
81
+ template: resolve(__dirname, '../public/info.ejs'),
82
+ filename: htmlFilename,
83
+ inject: false,
84
+ /**
85
+ * Passing arbitrary data to the template for display
86
+ */
87
+ moduleFederationDetails: JSON.stringify(moduleFederationOptions, undefined, 2),
88
+ }),
89
+ ],
90
+ };
91
+ };
92
+
93
+ module.exports = {
94
+ getFederatedPkgName,
95
+ getRemoteEntryUrl,
96
+ getRemoteEntry,
97
+ getWebpackMFConfigFragment,
98
+ federatedIndexExists,
99
+ };
@@ -0,0 +1,117 @@
1
+ const crypto = require('crypto');
2
+ const path = require('path');
3
+ const CopyPlugin = require('copy-webpack-plugin');
4
+ const fs = require('fs-extra');
5
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
6
+ const { DefinePlugin, ProgressPlugin } = require('webpack');
7
+ const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
8
+ const { appFileRules } = require('../rules/fileRules');
9
+ const { appScriptRules } = require('../rules/scriptRules');
10
+ const { appStyleRules } = require('../rules/styleRules');
11
+
12
+ // Avoid MD4 hash for OpenSSL 3 compatibility
13
+ // https://github.com/cockpit-project/starter-kit/commit/3220617fec508aabbbc226a87a165c21fb72e913
14
+ // Using Webpack v5.54.0+ and output.hashFunction = "xxhash64" should make this unnecessary, however
15
+ // builds still fail with an OpenSSL error in practice
16
+ const cryptoOrigCreateHash = crypto.createHash;
17
+ crypto.createHash = (algorithm) => cryptoOrigCreateHash(algorithm == 'md4' ? 'sha256' : algorithm);
18
+
19
+ const readFile = (filePath) => {
20
+ if (!filePath) return '';
21
+ const configPath = path.resolve(process.cwd(), filePath);
22
+ try {
23
+ return fs.readFileSync(configPath, 'utf8');
24
+ } catch (e) {
25
+ console.error(e);
26
+ return '';
27
+ }
28
+ };
29
+
30
+ /**
31
+ * Switching the '/' instead of 'auto', as webpack and perhaps the html-webpack-plugin seem to get confused over
32
+ * mime types, and this can block deep linking. Reading through the 'Practical Module Federation' guide, we may need
33
+ * to revisit this, dev v prod, resolving remotes.
34
+ */
35
+ const publicPath = typeof process.env.PUBLIC_PATH !== 'undefined' ? process.env.PUBLIC_PATH : '/';
36
+
37
+ /**
38
+ * Webpack common config factory used as a baseline across both production and development builds.
39
+ * Used mainly in conjunction with ./configFactory.js, but there are a few standalone consumers in foundation-ui.
40
+ *
41
+ * @returns A common webpack config.
42
+ */
43
+ module.exports = () => ({
44
+ entry: path.resolve(process.cwd(), './src/index.ts'),
45
+ plugins: [
46
+ new CopyPlugin({
47
+ patterns: [
48
+ {
49
+ from: path.resolve(__dirname, '../public'),
50
+ },
51
+ ],
52
+ }),
53
+ /**
54
+ * TODO: Test making this dynamic using .env files and the DotEnv Webpack plugin.
55
+ */
56
+ new DefinePlugin({
57
+ API_HOST: JSON.stringify(process.env.API_HOST),
58
+ DEFAULT_ORGANISATION: JSON.stringify(process.env.DEFAULT_ORGANISATION),
59
+ DEFAULT_USER: JSON.stringify(process.env.DEFAULT_USER),
60
+ DEFAULT_PASSWORD: JSON.stringify(process.env.DEFAULT_PASSWORD),
61
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV),
62
+ FORCE_HTTP: JSON.stringify(process.env.FORCE_HTTP),
63
+ HTTP_CONFIG: JSON.stringify(readFile(process.env.HTTP_CONFIG_PATH)),
64
+ SOCKET_EXT: JSON.stringify(process.env.SOCKET_EXT),
65
+ }),
66
+ new ProgressPlugin(),
67
+ new MiniCssExtractPlugin(),
68
+ /**
69
+ * Run via 'build:webpack:stats'.
70
+ */
71
+ ...(process.env.ANALYZE
72
+ ? [
73
+ new BundleAnalyzerPlugin({
74
+ reportTitle: `Webpack Visualizer`,
75
+ reportFilename: path.join(process.cwd(), './dist', 'webpack.stats.html'),
76
+ analyzerMode: 'static',
77
+ openAnalyzer: false,
78
+ }),
79
+ ]
80
+ : []),
81
+ ],
82
+ output: {
83
+ strictModuleErrorHandling: true,
84
+ strictModuleExceptionHandling: true,
85
+ path: path.resolve(process.cwd(), './dist'),
86
+ publicPath,
87
+ },
88
+ resolve: {
89
+ extensions: ['.ts', '.js'],
90
+ modules: ['node_modules'],
91
+ },
92
+ module: {
93
+ rules: [
94
+ appScriptRules.typescript(),
95
+
96
+ // Files
97
+ appFileRules.fonts(),
98
+ appFileRules.html(),
99
+ appFileRules.images(),
100
+
101
+ // Styles
102
+ appStyleRules.headCss(),
103
+ appStyleRules.css(),
104
+ appStyleRules.sass(),
105
+ ],
106
+ },
107
+ experiments: {
108
+ topLevelAwait: true,
109
+ lazyCompilation: false,
110
+ // outputModule: true,
111
+ },
112
+ performance: {
113
+ hints: false,
114
+ maxEntrypointSize: 512000,
115
+ maxAssetSize: 512000,
116
+ },
117
+ });
@@ -0,0 +1,32 @@
1
+ const portfinderSync = require('portfinder-sync');
2
+ const { merge } = require('webpack-merge');
3
+ const { devServers } = require('./devServers.js');
4
+ const commonConfigFactory = require('./webpack.common.js');
5
+
6
+ /**
7
+ * Webpack config factory for development.
8
+ * Used mainly in conjunction with ./configFactory.js, but there are a few standalone consumers in foundation-ui.
9
+ *
10
+ * @param port the target port to use.
11
+ * @returns Webpack config for development mode.
12
+ */
13
+ module.exports = (port = portfinderSync.getPort(process.env.PORT || 9000)) => {
14
+ return merge(commonConfigFactory(), {
15
+ mode: 'development',
16
+ devtool: 'inline-source-map', // CSP?
17
+ output: {
18
+ filename: '[name].js',
19
+ chunkFilename: '[name].[id].js',
20
+ sourceMapFilename: '[name].js.map',
21
+ // library: {
22
+ // // no name required for module
23
+ // type: 'module',
24
+ // },
25
+ },
26
+ devServer: devServers.default(port),
27
+ optimization: {
28
+ usedExports: false,
29
+ minimize: false,
30
+ },
31
+ });
32
+ };
@@ -0,0 +1,47 @@
1
+ /* eslint prefer-named-capture-group: "off" */
2
+ // In this config named capturing isn't desired.
3
+ // May cause adverse affects with webpack.
4
+ const TerserPlugin = require('terser-webpack-plugin');
5
+ const { merge } = require('webpack-merge');
6
+ const commonConfigFactory = require('./webpack.common.js');
7
+
8
+ const vendorCacheGroup = {
9
+ vendor: {
10
+ test: /[\\/]node_modules[\\/]/,
11
+ name: (module) => {
12
+ const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
13
+ // npm package names are URL-safe, but some servers don't like @ symbols
14
+ return `npm.${packageName.replace('@', '')}`;
15
+ },
16
+ },
17
+ };
18
+
19
+ /**
20
+ * Webpack config factory for production.
21
+ * Used mainly in conjunction with ./configFactory.js, but there are a few standalone consumers in foundation-ui.
22
+ *
23
+ * @returns Webpack config for production mode.
24
+ */
25
+ module.exports = () => {
26
+ return merge(commonConfigFactory(), {
27
+ mode: 'production',
28
+ devtool: 'source-map',
29
+ output: {
30
+ filename: '[name].[contenthash].js',
31
+ chunkFilename: '[name].[id].[contenthash].js',
32
+ sourceMapFilename: '[name].[contenthash].js.map',
33
+ },
34
+ optimization: {
35
+ usedExports: true,
36
+ minimize: true,
37
+ minimizer: [new TerserPlugin()],
38
+ splitChunks: {
39
+ chunks: 'all',
40
+ maxInitialRequests: 100,
41
+ cacheGroups: {
42
+ ...vendorCacheGroup,
43
+ },
44
+ },
45
+ },
46
+ });
47
+ };
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { run, resolveBin } from '@genesislcap/build-kit';
2
+ import type { BuildContext } from '@genesislcap/build-kit';
3
+
4
+ export default async (ctx: BuildContext) => {
5
+ const {
6
+ dirs: { cwd },
7
+ cli: { isDev, isAnalyze, isBuild, options },
8
+ enable: { mft },
9
+ } = ctx;
10
+
11
+ if (mft) {
12
+ const mftCLI = await resolveBin('make-federated-types', '@pixability-ui/federated-types');
13
+ run(cwd, `${mftCLI}`);
14
+ }
15
+
16
+ const webpack = await resolveBin('webpack');
17
+
18
+ if (isDev) {
19
+ const open = !options.open ? '--no-open' : '--open';
20
+ const https = options.https ? '--https' : '';
21
+ run(cwd, `${webpack} serve ${open} ${https}`);
22
+ } else if (isAnalyze) {
23
+ run(cwd, `${webpack}`, true, true, { ...process.env, ANALYZE: '1' });
24
+ } else if (isBuild) {
25
+ run(cwd, `${webpack}`);
26
+ } else {
27
+ throw new Error(`Unrecognised command: ${JSON.stringify(options)}`);
28
+ }
29
+ };
@@ -0,0 +1,26 @@
1
+ /* eslint prefer-named-capture-group: "off" */
2
+ // In this config named capturing isn't desired.
3
+ // May cause adverse affects with webpack.
4
+
5
+ const appFileRules = {
6
+ fonts: () => ({
7
+ test: /\.(woff|woff2|eot|ttf|otf)$/i,
8
+ type: 'asset/resource',
9
+ }),
10
+ html: () => ({
11
+ test: /\.html$/,
12
+ use: [
13
+ {
14
+ loader: 'html-loader',
15
+ },
16
+ ],
17
+ }),
18
+ images: () => ({
19
+ test: /\.(png|svg|jpg|jpeg|gif)$/i,
20
+ type: 'asset/resource',
21
+ }),
22
+ };
23
+
24
+ module.exports = {
25
+ appFileRules,
26
+ };
@@ -0,0 +1,21 @@
1
+ const path = require('path');
2
+
3
+ const appScriptRules = {
4
+ typescript: () => ({
5
+ test: /\.ts$/i,
6
+ exclude: /node_modules/,
7
+ use: [
8
+ {
9
+ loader: 'ts-loader',
10
+ options: {
11
+ configFile: path.resolve(process.cwd(), './tsconfig.json'),
12
+ projectReferences: true,
13
+ },
14
+ },
15
+ ],
16
+ }),
17
+ };
18
+
19
+ module.exports = {
20
+ appScriptRules,
21
+ };
@@ -0,0 +1,60 @@
1
+ const path = require('path');
2
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3
+
4
+ const mode = process.env.NODE_ENV || 'development';
5
+ const prod = mode === 'production';
6
+
7
+ const miniCssExtractLoader = () => ({
8
+ loader: MiniCssExtractPlugin.loader,
9
+ options: {
10
+ esModule: true,
11
+ modules: {
12
+ namedExport: true,
13
+ },
14
+ },
15
+ });
16
+
17
+ const cssLoader = (importLoaders = 1, useHash = true) => ({
18
+ loader: 'css-loader',
19
+ options: {
20
+ importLoaders,
21
+ // modules: {
22
+ // namedExport: true,
23
+ // localIdentName: '[local]' + (useHash ? '--[hash:base64:5]' : ''),
24
+ // exportLocalsConvention: 'camelCaseOnly',
25
+ // },
26
+ },
27
+ });
28
+
29
+ const postCSSLoader = () => ({
30
+ loader: 'postcss-loader',
31
+ options: {
32
+ postcssOptions: {
33
+ config: path.resolve(__dirname, '../config/postcss.config.js'),
34
+ },
35
+ },
36
+ });
37
+
38
+ const headCssPatterns = [/main\.css$/i, /head\.css$/i, /index\.css$/i];
39
+
40
+ const appStyleRules = {
41
+ headCss: () => ({
42
+ test: /\.css$/i,
43
+ include: headCssPatterns,
44
+ use: ['style-loader', cssLoader(), postCSSLoader()],
45
+ }),
46
+ css: (useHash = true) => ({
47
+ test: /\.css$/i,
48
+ exclude: [...headCssPatterns],
49
+ use: [cssLoader(), postCSSLoader()],
50
+ }),
51
+ sass: (useHash = true) => ({
52
+ test: /\.(sa|sc)ss$/i,
53
+ exclude: [...headCssPatterns],
54
+ use: [cssLoader(2), postCSSLoader(), 'sass-loader'],
55
+ }),
56
+ };
57
+
58
+ module.exports = {
59
+ appStyleRules,
60
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "../../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "declarationDir": "./dist",
5
+ "lib": [
6
+ "ES2015",
7
+ "ES2016",
8
+ "ES2017",
9
+ "ES2019",
10
+ ],
11
+ "module": "commonjs",
12
+ "outDir": "./dist",
13
+ "rootDir": "./src",
14
+ },
15
+ "include": [
16
+ "src/**/*"
17
+ ]
18
+ }