简体   繁体   中英

How to update multiple bundled js files using webpack?

I have a simple app in which require a user to provide certain pieces of information as follows.

  1. Please provide your domain .

    user: www.google.com

  2. Please provide your vast URL.

    user: www.vast.xx.com

  3. Please select position. a) Bottom left. b) Bottom right.

    user: b) Bottom right

After the user provides these pieces of information the button generate code appears, the user clicks to generate code. He gets the following 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>

Here is my full webpack config file: 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.

It might be easier for you to have a single widget file (generated by you with the default configuration) and use the user-provided information as parameters.

domainName: www.google.com vastUrl: www.vast.xx.com position: Bottom right

 (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>

Afterward, use the variables in your widget.

Then, updating the color of the widget will affect all the installed widgets and will keep the user's configuration.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM