如何使用 webpack 更新多个捆绑的 js 文件?

Posted

技术标签:

【中文标题】如何使用 webpack 更新多个捆绑的 js 文件?【英文标题】:How to update multiple bundled js files using webpack? 【发布时间】:2020-05-18 16:39:48 【问题描述】:

我有一个简单的应用程序,其中要求用户提供以下某些信息。

    请提供您的域名。

    用户:www.google.com

    请提供您的网址。

    用户:www.vast.xx.com

    请选择职位。 a) 左下角。 b) 右下角。

    用户:b) 右下角

用户提供这些信息后,出现generate code按钮,用户点击生成代码。他得到以下代码。

 (function (w,d,s,o,f,js,fjs) 
            w['JS-Widget']=o;w[o] = w[o] || function ()  (w[o].q = w[o].q || []).push(arguments) ;
            js = d.createElement(s), fjs = d.getElementsByTagName(s)[0];
            js.id = o; js.src = f; js.async = 1; fjs.parentNode.insertBefore(js, fjs);
        (window, document, 'script', 'mw', 'www.mywebisite.com/widget123.js'));
        mw('init',  someConfiguration: 448 );
        mw('message', 'x');
    </script>

这是我完整的 webpack 配置文件:webpack config 有了这个脚本,用户就可以在自己的网站上使用了,这里要注意的是www.mywebisite.com/widget123.js这是webpack生成的捆绑js文件,如下所示。

这是我用来通过运行命令npm run build 使用 webpack 生成捆绑的 js 文件的部分代码

const htmlWebpackPlugin = require('html-webpack-plugin');
// ...
return [
  entry: './src/main.js',
  plugins: [
    new HtmlWebpackPlugin( title: 'Caching' ),
  ],
  output: 
    **filename: 'widget.[contenthash].js',**
    path: path.resolve(bundleOutputDir),
  
]

要在每次用户生成新代码时生成捆绑的 js 文件,我需要运行 npm run build 来执行此操作,我正在使用 WebSockets 向服务器发送命令,如下所示。

HTML (client)

    <html>
    <body>
     <button onClick="sendCommands()"> Generate Code</button>
    </body>
    <script>

    const ws = new WebSocket('ws://localhost:9898/');
   function sendCommands()
    ws.onopen = function() 
        console.log('WebSocket Client Connected');
        ws.send('npm run build');
    ;
    
    ws.onmessage = function(e) 
      console.log("Received: '" + e.data + "'");
    ;

    </script>
    </html>

这里是 Server.js

const http = require('http');
const WebSocketServer = require('websocket').server;
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const server = http.createServer();
server.listen(9898);

const wsServer = new WebSocketServer(
    httpServer: server
);

wsServer.on('request', function(request) 
    const connection = request.accept(null, request.origin);

    connection.on('message', function(message) 
      console.log(message.utf8Data);
      const  stdout, stderr  = await exec(message.utf8Data);
      console.log('stdout:', stdout);
      console.log('stderr:', stderr);
      connection.sendUTF('Hi this is WebSocket server!');
    );
    connection.on('close', function(reasonCode, description) 
        console.log('Client has disconnected.');
    );
);

问题:

现在假设我有 4 个用户,每个用户都生成了 他们自己的 js 捆绑文件在 dist 文件夹中我将有四个文件,例如 这个:widget4321.js, widget3345.js, widget1123.js, widget4321.js

假设我更改了小部件的颜色,如何使用 webpack 更新这些文件?

注意:如果您有其他解决方案,请随时提供,谢谢。

【问题讨论】:

那么不要使用contenthash。使用用户名的哈希值,这样每个人都将拥有自己的唯一 URL,该 URL 将随着时间的推移保持稳定而不会暴露详细信息。 如果它是关于样式不是使用javascript动态加载css选项,那么当你更新你的服务上的css时,所有客户端都将使用新的css。如果您想将一些功能添加到您的小部件中(也许您更新了 javascript),那么您可以拥有一个小型数据库来存储用户信息和生成的捆绑文件之间的引用。然后,当您想要更新文件时,您重新编译它们并用新内容覆盖。 @pawel cam 你提供了一些例子吗? @codtex 现在我该怎么做?您可以在代码示例中提供您的解决方案吗?我是 webpack 的新手,谢谢 可能类似于在 env 中设置用户数据的哈希值,例如UID=df98ad npm run build 然后 filename: widget$process.env.UID.js 在 webpack 配置中,或者使用 widget.js 作为文件名和 path: dist/$UID/。要在代码库更改后重建小部件,您还需要保留原始有效负载并重新使用它,例如将它们存储为buildparams_$UID.json 【参考方案1】:

拥有一个小部件文件(由您使用默认配置生成)并使用用户提供的信息作为参数可能会更容易。

域名:www.google.com 巨大的网址:www.vast.xx.com 位置:右下

 (function (w,d,s,o,f,js,fjs) 
            w['JS-Widget']=o;w[o] = w[o] || function ()  (w[o].q = w[o].q || []).push(arguments) ;
            js = d.createElement(s), fjs = d.getElementsByTagName(s)[0];
            js.id = o; js.src = f; js.async = 1; fjs.parentNode.insertBefore(js, fjs);
        (window, document, 'script', 'mw', 'www.mywebisite.com/widget123.js'));
        mw('init',  
                       someConfiguration: 448, 
                       domainName: 'www.google.com', 
                       vastUrl: 'www.vast.xx.com', 
                       position: 'bottom right'
                    );
        mw('message', 'x');
    </script>

然后,使用小部件中的变量。

那么,更新小部件的颜色会影响所有已安装的小部件,并会保留用户的配置。

【讨论】:

嗨,这可能是最简单的方法,但在 JavaScript 代码中,我们只需要提供捆绑的 js 文件,而无需提供用户信息,上述解决方案是不可接受的,请注意用户信息应被隐藏【参考方案2】:

因为您使用的是'widget.[contenthash].js' 内容哈希,并且每次更改文件内容时它都会更改,因此您无法将文件与用户关联

你可以做的不是使用contenthash,而是可以做这样的事情


  output 
    filename: `widget.$someUserSpecificId.js`
    ...
    ...
  

现在的问题是如何在配置中传递someUserSpecificId。为此,您可以使用 Webpack 的 environment-options

如果你导出一个函数而不是像这样的对象,现在在 webpack 配置中

function (env, arg) 
  return 
    ...
    ...
    output: 
      filename: `widget.$env.someUserSpecificId.js`
      ...
      ...
  

现在您可以使用 cli 选项传递env.someUserSpecificId

 webpack --env.someUserSpecificId=foo

现在您可以根据需要为任何用户更新任何捆绑包

注意请注意,您不要在文件名中使用实际的用户 ID,因为它将向客户端公开,而是为每个用户生成一些随机 ID,可以在客户端公开并且每个用户都是唯一的用户


上述

UPDATE 方法适用于更新某些特定捆绑包,但如果您想一次性更新所有捆绑包,则必须稍微调整逻辑

您可以这样做,而不是从命令行参数传递someUserSpecificId

const usersIdArray = ['userId1', 'userId2', ...otherUsersId];

const webpackConfig = userIdArray.map(someUserSpecificId => 
  return 
    ...
    ...
    output: 
      filename: `widget.$someUserSpecificId.js`
      ...
      ...
    
  ;
);

module.exports = webpackConfig;

它将为您提供多个 webpack 配置的数组,您可以将该数组直接传递给 webpack,webpack 将根据各自的配置更新所有文件see exporting multiple configuration

注意如果您有大量用户,请将您的任务分成小段

其他优化想法因为您正在您的服务器上运行此任务,所以最好考虑一些优化以减少重复性任务我现在的一个想法是您可以在第 1 部分中构建捆绑包. 将包含用户特定的配置 2. 将包含您的代码

因此,如果用户更改他的配置,您必须只构建该部分,如果您更改配置,那么您也必须只构建一次,因为您的通用代码对于所有用户(如主题)都是相同的

当您创建最终捆绑包时,只需将用户特定的配置与您的代码结合起来,这样您就可以减少重复性任务并且速度会快很多

【讨论】:

您好,您的解决方案您好 我可以一次更新所有捆绑的 js 文件吗?因为我不想单独更新这些文件,正如我所说,假设我决定为所有用户更改小部件的背景颜色, 是的,您也可以这样做,但要更新所有文件,您必须稍微调整逻辑。我也会在答案中更新那个案例 嗨,这是我尝试过但无法正常工作的配置文件,请查看:github.com/throne1986/embedable-javascript-widget-for-users/… @user9964622 有几个问题 1. 使用 块时不需要在箭头函数中返回 2. 你没有导出你的 webpackConfig @user9964622 这是一个简单的 javascript 文件,你可以使用任何东西,就像你可以使用 const userJson = fs.readFileSync(pathToJsonFile) 然后 const user = JSON.parse(userJson) 从 json 文件中读取一样

以上是关于如何使用 webpack 更新多个捆绑的 js 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何排除目录被 Webpack 捆绑?

如何使用 Webpack 捆绑 Express Js (NodeJs) 和 Pug 引擎?

AWS Elastic Beanstalk - 如何使用 npm 和 webpack 构建捆绑 JS

如何使用 webpack 将 html、js 和 css 捆绑在一个 html 文件中? [关闭]

如何从 Webpack 捆绑 JS 文件中排除 style-loaders、css-loader 源代码?

Angular Cli Webpack,如何添加或捆绑外部 js 文件?