2
0
Эх сурвалжийг харах

feat: Add ESM build support and update package exports

Updates #3764

- Configure RSPack to generate both CJS (.js) and ESM (.esm.js) builds
- Update package.json exports to properly reference both build formats:
  - ESM imports now point to dist/converse.esm.js
  - CJS requires continue using dist/converse.js

Use ESM build in dev.html
JC Brand 1 сар өмнө
parent
commit
a51993497f
3 өөрчлөгдсөн 135 нэмэгдсэн , 69 устгасан
  1. 67 30
      dev.html
  2. 4 4
      package.json
  3. 64 35
      rspack/rspack.build.js

+ 67 - 30
dev.html

@@ -11,38 +11,75 @@
     <link rel="manifest" href="./manifest.json">
     <link rel="shortcut icon" type="image/ico" href="images/favicon.ico"/>
     <link type="text/css" rel="stylesheet" media="screen" href="dist/converse.css" />
-    <script src="3rdparty/libsignal-protocol.js"></script>
-    <script src="dist/converse.js"></script>
-</head>
+    <!-- Modern browsers will execute this -->
+    <script type="module">
+        (async () => {
+            try {
+                // Feature detection
+                if (typeof window.Promise === 'undefined' ||
+                    typeof window.WeakMap === 'undefined') {
+                    throw new Error('Browser lacks required features');
+                }
 
-<body class="reset" style="background-color: var(--global-background-color)">
+                const { default: converse } = await import('./dist/converse.esm.js');
 
-<script>
-    converse.plugins.add('converse-debug', {
-        initialize () {
-            const { _converse } = this;
-            window._converse = _converse;
-        }
-    });
+                converse.plugins.add('converse-debug', {
+                    initialize () {
+                        // Expose for debugging but warn about direct usage
+                        if (window._converse) {
+                            console.warn('_converse already exists on window');
+                        }
+                        Object.defineProperty(window, '_converse', {
+                            get: () => this._converse,
+                            configurable: true // Allows tests to redefine
+                        });
+                    }
+                });
 
-    converse.initialize({
-        theme: 'nordic',
-        dark_theme: 'dracula',
-        auto_away: 300,
-        loglevel: 'debug',
-        show_background: true,
-        message_archiving: 'always',
-        muc_show_logs_before_join: true,
-        notify_all_room_messages: ['discuss@conference.conversejs.org'],
-        fetch_url_headers: true,
-        whitelisted_plugins: ['converse-debug'],
-        bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
-        // view_mode: 'overlayed',
-        show_controlbox_by_default: true,
-        // websocket_url: 'wss://conversejs.org/xmpp-websocket',
-        // websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
-        // connection_options: { worker: '/dist/shared-connection-worker.js' }
-    });
-</script>
+                await converse.initialize({
+                    theme: 'nordic',
+                    dark_theme: 'dracula',
+                    auto_away: 300,
+                    loglevel: 'debug',
+                    show_background: true,
+                    message_archiving: 'always',
+                    muc_show_logs_before_join: true,
+                    notify_all_room_messages: ['discuss@conference.conversejs.org'],
+                    fetch_url_headers: true,
+                    whitelisted_plugins: ['converse-debug'],
+                    bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
+                    show_controlbox_by_default: true,
+                    // view_mode: 'overlayed',
+                    // websocket_url: 'wss://conversejs.org/xmpp-websocket',
+                    // websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
+                    // connection_options: { worker: '/dist/shared-connection-worker.js' }
+                });
+            } catch (error) {
+                console.error('Failed to load Converse.js ESM:', error);
+                document.getElementById('fallback-script').hidden = false;
+            }
+        })();
+    </script>
+
+    <!-- Older browsers will execute this -->
+    <script nomodule id="fallback-script" hidden>
+        console.warn('Using legacy CJS build due to lack of module support');
+        document.write('<script src="dist/converse.js"><\/script>');
+    </script>
+
+    <!-- Error display -->
+    <div id="load-error" style="display:none; padding:1em; background:#fcc; margin:1em">
+        <h2>Loading Error</h2>
+        <p>Failed to load Converse.js. Please try:</p>
+        <ul>
+            <li>Using a modern browser (Chrome, Firefox, Edge, Safari)</li>
+            <li>Checking console for errors</li>
+        </ul>
+    </div>
+    <script>
+        window.addEventListener('error', () => {
+            document.getElementById('load-error').style.display = 'block';
+        });
+    </script>
 </body>
 </html>

+ 4 - 4
package.json

@@ -2,7 +2,6 @@
   "name": "converse.js",
   "version": "11.0.1",
   "description": "Browser based XMPP chat client",
-  "browser": "dist/converse.js",
   "workspaces": [
     "src/headless",
     "src/log"
@@ -11,7 +10,7 @@
     ".": {
       "import": {
         "types": "./src/types/index.d.ts",
-        "default": "./src/index.js"
+        "default": "./dist/converse.esm.js"
       },
       "require": {
         "types": "./types/index.d.ts",
@@ -22,8 +21,9 @@
     "./shared/*": "./src/shared/*"
   },
   "types": "./src/types/index.d.ts",
-  "main": "./src/index.js",
-  "module": "./src/index.js",
+  "browser": "dist/converse.js",
+  "main": "dist/converse.js",
+  "module": "dist/converse.esm.js",
   "files": [
     "CHANGES.md",
     "LICENSE.txt",

+ 64 - 35
rspack/rspack.build.js

@@ -3,40 +3,7 @@ const path = require('path');
 const { merge } = require('webpack-merge');
 const common = require('../rspack/rspack.common.js');
 
-const plugins = [
-    new rspack.CssExtractRspackPlugin({
-        filename: '../dist/converse.min.css',
-    }),
-    new rspack.CssExtractRspackPlugin({
-        filename: '../dist/converse.css',
-    }),
-    new rspack.CopyRspackPlugin({
-        patterns: [
-            { from: 'node_modules/strophe.js/src/shared-connection-worker.js', to: 'shared-connection-worker.js' },
-            { from: 'sounds', to: 'sounds' },
-            { from: 'images/favicon.ico', to: 'images/favicon.ico' },
-            { from: 'images/custom_emojis', to: 'images/custom_emojis' },
-            { from: 'logo/conversejs-filled-192.png', to: 'images/logo' },
-            { from: 'logo/conversejs-filled-512.png', to: 'images/logo' },
-            { from: 'logo/conversejs-filled-192.svg', to: 'images/logo' },
-            { from: 'logo/conversejs-filled-512.svg', to: 'images/logo' },
-            { from: 'logo/conversejs-filled.svg', to: 'images/logo' },
-            { from: 'logo/conversejs-gold-gradient.svg', to: 'images/logo' },
-            { from: 'src/shared/styles/webfonts', to: 'webfonts' },
-            { from: 'manifest.json', to: 'manifest.json' },
-        ],
-    }),
-];
-
-module.exports = merge(common, {
-    plugins,
-    entry: {
-        'converse': path.resolve(__dirname, '../src/entry.js'),
-        'converse.min': path.resolve(__dirname, '../src/entry.js'),
-    },
-    output: {
-        filename: '[name].js',
-    },
+const sharedConfig = {
     mode: 'production',
     optimization: {
         minimize: true,
@@ -98,4 +65,66 @@ module.exports = merge(common, {
             },
         ],
     },
-});
+};
+
+const plugins = [
+    new rspack.CssExtractRspackPlugin({
+        filename: '../dist/converse.min.css',
+    }),
+    new rspack.CssExtractRspackPlugin({
+        filename: '../dist/converse.css',
+    }),
+    new rspack.CopyRspackPlugin({
+        patterns: [
+            { from: 'node_modules/strophe.js/src/shared-connection-worker.js', to: 'shared-connection-worker.js' },
+            { from: 'sounds', to: 'sounds' },
+            { from: 'images/favicon.ico', to: 'images/favicon.ico' },
+            { from: 'images/custom_emojis', to: 'images/custom_emojis' },
+            { from: 'logo/conversejs-filled-192.png', to: 'images/logo' },
+            { from: 'logo/conversejs-filled-512.png', to: 'images/logo' },
+            { from: 'logo/conversejs-filled-192.svg', to: 'images/logo' },
+            { from: 'logo/conversejs-filled-512.svg', to: 'images/logo' },
+            { from: 'logo/conversejs-filled.svg', to: 'images/logo' },
+            { from: 'logo/conversejs-gold-gradient.svg', to: 'images/logo' },
+            { from: 'src/shared/styles/webfonts', to: 'webfonts' },
+            { from: 'manifest.json', to: 'manifest.json' },
+        ],
+    }),
+];
+
+module.exports = [
+    // CJS Build
+    merge(common, {
+        ...sharedConfig,
+        plugins,
+        entry: {
+            'converse': path.resolve(__dirname, '../src/entry.js'),
+            'converse.min': path.resolve(__dirname, '../src/entry.js'),
+        },
+        output: {
+            filename: '[name].js',
+            library: {
+                type: 'umd',
+                name: 'converse'
+            }
+        },
+    }),
+    // ESM Build
+    merge(common, {
+        ...sharedConfig,
+        plugins,
+        entry: {
+            'converse': path.resolve(__dirname, '../src/entry.js'),
+            'converse.min': path.resolve(__dirname, '../src/entry.js'),
+        },
+        experiments: {
+            outputModule: true
+        },
+        output: {
+            filename: '[name].esm.js',
+            library: {
+                type: 'module'
+            }
+        },
+    })
+];