如何使用webpack更新多个捆绑的js文件? [英] How to update multiple bundled js files using webpack?

查看:91
本文介绍了如何使用webpack更新多个捆绑的js文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  1. 请提供您的域.

    用户:www.google.com

  2. 请提供您广泛的网址.

    用户:www.vast.xx.com

  3. 请选择位置. 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配置文件:

这是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个用户,每个用户都在其中生成 他们在dist文件夹中的js捆绑文件,我将有四个文件,例如 这个:widget4321.js, widget3345.js, widget1123.js, widget4321.js

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

注意:如果您有任何感谢,请随时提供另一种解决方案.

解决方案

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

您可以做的是代替使用contenthash,您可以执行以下操作

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

现在的问题是如何通过配置中的someUserSpecificId.为此,您可以使用Webpack的环境选项

如果您导出函数而不是像这样的对象,则现在处于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将根据各自的配置更新所有文件webpack config With this script, a user can use it on his website, the important thing here to note is www.mywebisite.com/widget123.js this is bundled js file generated by webpack as follow.

Here is part of my code I use to generate bundled js files using webpack by running a command npm run build

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),
  }
}]

To generate the bundled js file each time a user generates a new code I need to run npm run build to do that I am using WebSockets to send a command to the server as follows.

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>

Here is 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.');
    });
});

Problem :

Now let assume I have 4 users in which each of them have generated their own js bundle file in dist folder I will have four files like this: widget4321.js, widget3345.js, widget1123.js, widget4321.js

Assume I have changed the color of my widget, How do I update these files using webpack?.

Note: please be free to provide another solution if you have one thanks.

解决方案

Because you are using 'widget.[contenthash].js' content hash and it will change every time content of the file is changed so you can not associate a file with user

What you can do is instead of using contenthash you could do something like this

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

now the question is how you will get to pass the someUserSpecificId in configuration. To do that you can use Webpack's environment-options

now in webpack configuration if you export a function instead of object like this

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

and now you can pass the env.someUserSpecificId with cli option like

 webpack --env.someUserSpecificId=foo

now you can update any bundle for any user as you like

NOTE be aware that you don't use actual user id in filename because it will be exposed to client instead generate some random id for each user which is ok to expose on client and unique to each user


UPDATE method above described is good for updating some specific bundle but if you want to update all the bundle in one go you have to tweak the logic a bit

Instead of passing the someUserSpecificId from command line argument you can do this

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

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

module.exports = webpackConfig;

what it will do is it will give you a array of multiple webpack config and you can pass that array directly to webpack and webpack will update all the files according to respective config see exporting multiple configuration

Note if you have very large array of users please batch your task in small segment

Other Optimization idea because you are running this task on your server it would be good to think of some optimization to reduce repetitive task one idea i have right now is you can build bundles in two part 1. will contain user specific config 2. will contain your code

so if user change his configuration you have to build only that part and if you change your configuration then also you have to build that only once because your common code will be same for all users ( like theme )

and when you creating final bundle just combine user-specific configuration with your code that way you can reduce repetitive task and it would be a lot faster

这篇关于如何使用webpack更新多个捆绑的js文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆