@mainset/bundler-webpack 0.3.4 → 0.3.6

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.
@@ -1,10 +1,9 @@
1
- const babelConfig = {
1
+ const BABEL_CONFIG__BROWSER = {
2
2
  presets: [
3
3
  [
4
4
  '@babel/preset-env',
5
5
  {
6
6
  targets: {
7
- node: 'current',
8
7
  chrome: '60',
9
8
  firefox: '60',
10
9
  safari: '11.1',
@@ -18,4 +17,22 @@ const babelConfig = {
18
17
  ],
19
18
  plugins: [],
20
19
  };
21
- export default babelConfig;
20
+ // NOTE: the SSR server bundle runs on Node only (never IE11/old browsers), so it
21
+ // gets its own, much looser preset-env target instead of inheriting the browser
22
+ // one — otherwise server code would be needlessly downleveled to ES5.
23
+ const BABEL_CONFIG__NODE = {
24
+ presets: [
25
+ [
26
+ '@babel/preset-env',
27
+ {
28
+ targets: {
29
+ node: 'current',
30
+ },
31
+ },
32
+ ],
33
+ '@babel/preset-react',
34
+ '@babel/preset-typescript',
35
+ ],
36
+ plugins: [],
37
+ };
38
+ export { BABEL_CONFIG__BROWSER, BABEL_CONFIG__NODE };
@@ -1,4 +1,4 @@
1
- import { merge } from '@mainset/toolkit-js';
1
+ import { merge } from 'webpack-merge';
2
2
  import csrDevServerWebappEnvBasedConfig from './webpack-config/dev-server.csr.config.mjs';
3
3
  import ssrEnvBasedConfigs from './webpack-config/webapp.ssr.config.mjs';
4
4
  const generateEnvBasedWebpackConfig = (extendedWebpackConfig = {}) => {
@@ -1,8 +1,19 @@
1
1
  import { resolveHostPackageNodeModulesPath, runtimePathById, } from '@mainset/cli/runtime';
2
- import { merge } from '@mainset/toolkit-js';
2
+ import CopyWebpackPlugin from 'copy-webpack-plugin';
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
+ import { merge } from 'webpack-merge';
5
6
  import { commonWebpackConfigFragment } from './common.fragment.mjs';
7
+ // The {public} folder is copied as-is into the build output, if present
8
+ const createPublicAssetsCopyPlugin = (outputPath) => new CopyWebpackPlugin({
9
+ patterns: [
10
+ {
11
+ from: path.join(runtimePathById.root, 'public'),
12
+ to: outputPath,
13
+ noErrorOnMissing: true, // optional: don't error if public doesn't exist
14
+ },
15
+ ],
16
+ });
6
17
  // The entry point for Global styles
7
18
  const cssGlobalStylesEntry = path.join(runtimePathById.src, 'styles', 'global.css');
8
19
  const scssGlobalStylesEntry = path.join(runtimePathById.src, 'styles', 'global.scss');
@@ -16,4 +27,4 @@ if (fs.existsSync(scssGlobalStylesEntry))
16
27
  const commonWebappWebpackConfigFragment = merge(commonWebpackConfigFragment, {
17
28
  entry: defaultEntry,
18
29
  });
19
- export { commonWebappWebpackConfigFragment };
30
+ export { commonWebappWebpackConfigFragment, createPublicAssetsCopyPlugin };
@@ -9,8 +9,10 @@ const commonWebpackConfigFragment = {
9
9
  BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT,
10
10
  ...IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS,
11
11
  Object.assign(Object.assign({}, FONTS__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK), { type: 'asset/resource', generator: {
12
- filename: '[name].[hash].[ext]',
13
- outputPath: 'dist/assets/fonts',
12
+ filename: '[name].[contenthash:8].[ext]',
13
+ // NOTE: the following paths are relative to the webpack output path (e.g. dist/)
14
+ outputPath: 'assets/fonts/',
15
+ publicPath: 'assets/fonts/',
14
16
  } }),
15
17
  ],
16
18
  },
@@ -24,6 +26,7 @@ const commonWebpackConfigFragment = {
24
26
  // Extra / custom
25
27
  '.ts',
26
28
  '.tsx',
29
+ '.jsx',
27
30
  ],
28
31
  },
29
32
  };
@@ -1,25 +1,14 @@
1
1
  import { runtimePathById } from '@mainset/cli/runtime';
2
- import { merge } from '@mainset/toolkit-js';
3
- import CopyWebpackPlugin from 'copy-webpack-plugin';
4
2
  import fs from 'fs';
5
3
  import path from 'path';
6
- import { commonWebappWebpackConfigFragment } from './common-webapp.fragment.mjs';
4
+ import { merge } from 'webpack-merge';
5
+ import { commonWebappWebpackConfigFragment, createPublicAssetsCopyPlugin, } from './common-webapp.fragment.mjs';
7
6
  // The entry point for the CSR webapp
8
7
  const defaultEntry = path.join(runtimePathById.src, 'index.ts');
9
8
  const csrEntry = path.join(runtimePathById.src, 'index.csr.ts');
10
9
  const bundlerEntry = fs.existsSync(csrEntry) ? csrEntry : defaultEntry;
11
10
  const csrWebappWebpackConfigFragment = merge(commonWebappWebpackConfigFragment, {
12
11
  entry: [bundlerEntry],
13
- plugins: [
14
- new CopyWebpackPlugin({
15
- patterns: [
16
- {
17
- from: path.join(runtimePathById.root, 'public'),
18
- to: path.join(runtimePathById.dist),
19
- noErrorOnMissing: true, // optional: don't error if public doesn't exist
20
- },
21
- ],
22
- }),
23
- ],
12
+ plugins: [createPublicAssetsCopyPlugin(runtimePathById.dist)],
24
13
  });
25
14
  export { csrWebappWebpackConfigFragment };
@@ -1,23 +1,27 @@
1
1
  import { resolveHostPackageNodeModulesPath } from '@mainset/cli/runtime';
2
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3
- // @ts-ignore
4
- import babelConfig from '../../../babel.config.mjs';
5
- const BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT = {
2
+ import { BABEL_CONFIG__BROWSER, BABEL_CONFIG__NODE, } from '../../../babel.config.mjs';
3
+ const createBabelLoaderRule = (options) => ({
6
4
  test: /\.((ts|mts|tsx)|(js|mjs|jsx))$/,
7
5
  exclude: /node_modules/,
8
6
  use: {
9
7
  loader: resolveHostPackageNodeModulesPath('@mainset/bundler-webpack', 'babel-loader'),
10
- options: babelConfig,
8
+ options,
11
9
  },
12
- };
10
+ });
11
+ const BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT = createBabelLoaderRule(BABEL_CONFIG__BROWSER);
12
+ // NOTE: dedicated rule for the SSR server bundle (target: 'node') so it uses
13
+ // {BABEL_CONFIG__NODE} instead of the browser-targeted preset-env config
14
+ const SSR_SERVER_BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT = createBabelLoaderRule(BABEL_CONFIG__NODE);
13
15
  const IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS = [
14
16
  {
15
17
  test: /\.(svg|png)$/,
16
18
  exclude: /\.source\.svg$/,
17
19
  type: 'asset/resource',
18
20
  generator: {
19
- filename: '[name].[hash].[ext]',
20
- outputPath: 'dist/assets/images',
21
+ filename: '[name].[contenthash:8].[ext]',
22
+ // NOTE: the following paths are relative to the webpack output path (e.g. dist/)
23
+ outputPath: 'assets/images/',
24
+ publicPath: 'assets/images/',
21
25
  },
22
26
  },
23
27
  {
@@ -25,4 +29,4 @@ const IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS = [
25
29
  type: 'asset/source',
26
30
  },
27
31
  ];
28
- export { BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS, };
32
+ export { BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS, SSR_SERVER_BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, };
@@ -1,10 +1,9 @@
1
1
  var _a;
2
2
  import { runtimePathById } from '@mainset/cli/runtime';
3
- import { merge } from '@mainset/toolkit-js';
4
- import CopyWebpackPlugin from 'copy-webpack-plugin';
5
3
  import fs from 'fs';
6
4
  import path from 'path';
7
- import { commonWebappWebpackConfigFragment } from './common-webapp.fragment.mjs';
5
+ import { merge } from 'webpack-merge';
6
+ import { commonWebappWebpackConfigFragment, createPublicAssetsCopyPlugin, } from './common-webapp.fragment.mjs';
8
7
  // The entry point for the SSR webapp
9
8
  const defaultEntry = path.join(runtimePathById.src, 'index.ts');
10
9
  const ssrEntry = path.join(runtimePathById.src, 'index.ssr.ts');
@@ -17,16 +16,6 @@ commonWebappWebpackConfigFragment, {
17
16
  output: {
18
17
  path: ssrPublicOutputPath,
19
18
  },
20
- plugins: [
21
- new CopyWebpackPlugin({
22
- patterns: [
23
- {
24
- from: path.join(runtimePathById.root, 'public'),
25
- to: ssrPublicOutputPath,
26
- noErrorOnMissing: true, // optional: don't error if public doesn't exist
27
- },
28
- ],
29
- }),
30
- ],
19
+ plugins: [createPublicAssetsCopyPlugin(ssrPublicOutputPath)],
31
20
  });
32
21
  export { ssrWebappWebpackConfigFragment };
@@ -1,8 +1,8 @@
1
1
  import { runtimePathById } from '@mainset/cli/runtime';
2
- import { merge } from '@mainset/toolkit-js';
3
2
  import fs from 'fs';
4
3
  import path from 'path';
5
4
  import { pathToFileURL } from 'url';
5
+ import { merge } from 'webpack-merge';
6
6
  import csrWebappEnvBasedConfig from './webapp.csr.config.mjs';
7
7
  const proxyConfigPath = path.join(runtimePathById.config, 'proxy.config.mjs');
8
8
  const proxyConfigByPath = fs.existsSync(proxyConfigPath)
@@ -1,8 +1,8 @@
1
1
  import { NODE_ENV, resolveHostPackageNodeModulesPath, runtimePathById, } from '@mainset/cli/runtime';
2
- import { merge } from '@mainset/toolkit-js';
3
2
  import path from 'path';
3
+ import { merge } from 'webpack-merge';
4
4
  import { commonWebpackConfigFragment } from './config-fragments/common.fragment.mjs';
5
- import { BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, CSS_LOADER__DEV_RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK, CSS_LOADER__PROD_RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK, CSS_MODULES__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK, CSS_STYLES__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK, CSS_STYLES__RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK, FONTS__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK, IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS, } from './config-fragments/module-rules/index.mjs';
5
+ import { CSS_LOADER__DEV_RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK, CSS_LOADER__PROD_RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK, CSS_MODULES__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK, CSS_STYLES__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK, CSS_STYLES__RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK, FONTS__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK, IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS, SSR_SERVER_BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, } from './config-fragments/module-rules/index.mjs';
6
6
  const nullLoaderModuleRules = [
7
7
  FONTS__RULE_TEST_REGEX__WEBPACK_CONFIG_CHUNK,
8
8
  ].map((ruleTestRegexWebpackConfigFragment) => (Object.assign(Object.assign({}, ruleTestRegexWebpackConfigFragment), { use: resolveHostPackageNodeModulesPath('@mainset/bundler-webpack', 'null-loader') })));
@@ -36,7 +36,7 @@ const ssrServerCommonWebpackConfigFragment = {
36
36
  module: {
37
37
  rules: [
38
38
  // common config
39
- BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT,
39
+ SSR_SERVER_BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT,
40
40
  ...IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS,
41
41
  // do NOT bundle in SSR mode, because they are not used during rendering on the server
42
42
  ...nullLoaderModuleRules,
@@ -63,8 +63,6 @@ const generateSSRCssStylesRuleWebpackConfigFragment = ({ mode, }) => {
63
63
  // without including or compiling CSS into the server bundle.
64
64
  },
65
65
  },
66
- }, {
67
- isSourceObjMutated: false,
68
66
  }),
69
67
  ...CSS_STYLES__RULE_USE_OPTIONS__WEBPACK_CONFIG_CHUNK,
70
68
  ] }),
@@ -89,6 +87,7 @@ const ssrServerProdWebpackConfigFragment = {
89
87
  };
90
88
  const ssrServerDevWebpackConfigFragment = {
91
89
  mode: 'development',
90
+ devtool: 'inline-source-map',
92
91
  module: {
93
92
  rules: [
94
93
  generateSSRCssStylesRuleWebpackConfigFragment({
@@ -1,7 +1,7 @@
1
1
  import { NODE_ENV, runtimePathById } from '@mainset/cli/runtime';
2
- import { merge } from '@mainset/toolkit-js';
3
2
  import HtmlWebpackPlugin from 'html-webpack-plugin';
4
3
  import path from 'path';
4
+ import { merge } from 'webpack-merge';
5
5
  import { csrWebappWebpackConfigFragment } from './config-fragments/csr-webapp.fragment.mjs';
6
6
  import { devWebpackConfigFragment } from './config-fragments/dev.fragment.mjs';
7
7
  import { prodWebpackConfigFragment } from './config-fragments/prod.fragment.mjs';
@@ -1,7 +1,7 @@
1
1
  import { NODE_ENV, runtimePathById } from '@mainset/cli/runtime';
2
- import { merge } from '@mainset/toolkit-js';
3
2
  import HtmlWebpackPlugin from 'html-webpack-plugin';
4
3
  import path from 'path';
4
+ import { merge } from 'webpack-merge';
5
5
  import { devWebpackConfigFragment } from './config-fragments/dev.fragment.mjs';
6
6
  import { prodWebpackConfigFragment } from './config-fragments/prod.fragment.mjs';
7
7
  import { ssrWebappWebpackConfigFragment } from './config-fragments/ssr-webapp.fragment.mjs';
@@ -0,0 +1,21 @@
1
+ declare const BABEL_CONFIG__BROWSER: {
2
+ presets: (string | (string | {
3
+ targets: {
4
+ chrome: string;
5
+ firefox: string;
6
+ safari: string;
7
+ edge: string;
8
+ ie: string;
9
+ };
10
+ })[])[];
11
+ plugins: never[];
12
+ };
13
+ declare const BABEL_CONFIG__NODE: {
14
+ presets: (string | (string | {
15
+ targets: {
16
+ node: string;
17
+ };
18
+ })[])[];
19
+ plugins: never[];
20
+ };
21
+ export { BABEL_CONFIG__BROWSER, BABEL_CONFIG__NODE };
@@ -1,4 +1,4 @@
1
1
  import type { Configuration as WebpackConfig } from 'webpack';
2
2
  import type { Configuration as DevServerConfig } from 'webpack-dev-server';
3
- declare const generateEnvBasedWebpackConfig: (extendedWebpackConfig?: WebpackConfig & DevServerConfig) => (WebpackConfig & DevServerConfig) | WebpackConfig[];
3
+ declare const generateEnvBasedWebpackConfig: (extendedWebpackConfig?: WebpackConfig & DevServerConfig) => WebpackConfig[] | (WebpackConfig & DevServerConfig);
4
4
  export { generateEnvBasedWebpackConfig };
@@ -1,2 +1,4 @@
1
+ import CopyWebpackPlugin from 'copy-webpack-plugin';
2
+ declare const createPublicAssetsCopyPlugin: (outputPath: string) => CopyWebpackPlugin;
1
3
  declare const commonWebappWebpackConfigFragment: import("webpack").Configuration;
2
- export { commonWebappWebpackConfigFragment };
4
+ export { commonWebappWebpackConfigFragment, createPublicAssetsCopyPlugin };
@@ -1,4 +1,5 @@
1
1
  import type { RuleSetRule } from 'webpack';
2
2
  declare const BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT: RuleSetRule;
3
+ declare const SSR_SERVER_BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT: RuleSetRule;
3
4
  declare const IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS: RuleSetRule[];
4
- export { BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS, };
5
+ export { BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, IMAGES__RULE__WEBPACK_CONFIG_FRAGMENTS, SSR_SERVER_BABEL_LOADER__RULE__WEBPACK_CONFIG_FRAGMENT, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mainset/bundler-webpack",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Bundler for web apps",
5
5
  "homepage": "https://github.com/mainset/dev-stack-fe/tree/main/packages/bundler-webpack",
6
6
  "bugs": {
@@ -46,17 +46,16 @@
46
46
  "terser-webpack-plugin": "^5.6.1",
47
47
  "webpack": "^5.108.4",
48
48
  "webpack-cli": "^7.2.1",
49
- "webpack-dev-server": "^6.0.0"
49
+ "webpack-dev-server": "^6.0.0",
50
+ "webpack-merge": "^6.0.1"
50
51
  },
51
52
  "devDependencies": {
52
- "@mainset/dev-stack-fe": "^0.2.2",
53
- "@mainset/toolkit-js": "^0.2.1",
54
- "@mainset/cli": "^0.6.0"
53
+ "@mainset/cli": "^0.7.0",
54
+ "@mainset/dev-stack-fe": "^0.2.2"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@mainset/cli": ">=0.5.0 <1.0.0",
58
- "@mainset/dev-stack-fe": ">=0.2.0 <1.0.0",
59
- "@mainset/toolkit-js": ">=0.1.0 <1.0.0"
58
+ "@mainset/dev-stack-fe": ">=0.2.0 <1.0.0"
60
59
  },
61
60
  "scripts": {
62
61
  "build": "ms-cli source-code --exec compile",
@@ -1,9 +1,47 @@
1
+ // NOTE: keep in sync with the module rules in
2
+ // ./src/webpack-config/config-fragments/module-rules/module-rules.chunk.mts —
3
+ // declaring a pattern the bundler does not resolve makes an import type-check
4
+ // and then fail at build time.
5
+ // !IMPORTANT: TypeScript picks a wildcard by longest prefix, and every pattern
6
+ // below has an empty prefix — so ties are won by the FIRST declaration. The
7
+ // specific patterns must stay above the generic ones, otherwise
8
+ // {styles.module.css} resolves as a plain stylesheet and {icon.source.svg} as a
9
+ // {*.svg} asset URL.
10
+
11
+ // CSS Modules: map of local class name to the generated one
12
+ declare module '*.module.css' {
13
+ const styles: { [className: string]: string };
14
+ export = styles;
15
+ }
1
16
  declare module '*.module.scss' {
2
17
  const styles: { [className: string]: string };
3
18
  export = styles;
4
19
  }
20
+ declare module '*.module.sass' {
21
+ const styles: { [className: string]: string };
22
+ export = styles;
23
+ }
5
24
 
25
+ // NOTE: original, unprocessed SVG content
6
26
  declare module '*.source.svg' {
7
27
  const content: string;
8
28
  export default content;
9
29
  }
30
+
31
+ // NOTE: plain stylesheets are imported for their side effect only
32
+ // ({import './styles.css'}), so they expose no meaningful binding. They need a
33
+ // declaration at all only once {noUncheckedSideEffectImports} is enabled —
34
+ // TypeScript does not check bare side-effect imports by default.
35
+ declare module '*.css';
36
+ declare module '*.scss';
37
+ declare module '*.sass';
38
+
39
+ // NOTE: {asset/resource} — emits the file and exports its public URL
40
+ declare module '*.png' {
41
+ const src: string;
42
+ export default src;
43
+ }
44
+ declare module '*.svg' {
45
+ const src: string;
46
+ export default src;
47
+ }