nikushi / minipack

Minipack, a gem for minimalists, which can integrates Rails with webpack. It is an alternative to Webpacker.
MIT License
115 stars 22 forks source link

[QUESTION] Is assets-webpack-plugin compatible with minipack? #36

Closed aesyondu closed 4 years ago

aesyondu commented 4 years ago

I just read your blog and would have loved to have read it one week ago, before I started implementing my own implementation. I see that either webpack-manifest-plugin or webpack-assets-manifest are supported.

I too did not like depending on yarn which webpacker forced you to. I saw this comment and installed assets-webpack-plugin. It even has a rails integration guide, with a super minimalist helper function:

def script_for(bundle)
  path = Rails.root.join('app', 'views', 'webpack-assets.json') # This is the file generated by the plug-in
  file = File.read(path)
  json = JSON.parse(file)
  json[bundle]['js']
end

My question is, will assets-webpack-plugin work out of the box with minipack? The manifest.json file it outputs looks like this:

{
    "bundleone": {
        "js": "/js/bundleone_2bb80372ebe8047a68d4.bundle.js",
        "css": "/css/bundleone_abcd.css"
    },
    "bundletwo": {
        "js": "/js/bundletwo_2bb80372ebe8047a68d4.bundle.js"
    }
}
aesyondu commented 4 years ago

I see that the manifest format is different. There is a processOutput option in the assets-webpack-plugin, where one can manipulate the manifest.json output. I suppose I could try that.

Or I could also try to create a PR to provide additional support for this type of format, would you be willing to accept that? I have no experience yet in developing ruby gems, but I'm willing to try.

Lastly, I could just change my dependency from assets-webpack-plugin to webpack-assets-manifest.

I wouldn't have this problem if I just read your blog earlier 😅

aesyondu commented 4 years ago

The naive implementation of the first option I mentioned was easier than I thought, I added the flatten function to convert the json schema from { bundle: { fileExtension: filePath } } to { bundle.fileExtension: filePath } :

{
  processOutput: function processOutput(assets) {
    function sortObject(object) {
      var sortedObj = {},
        keys = Object.keys(object);

      keys.sort(function (key1, key2) {
        (key1 = key1.toLowerCase()), (key2 = key2.toLowerCase());
        if (key1 < key2) return -1;
        if (key1 > key2) return 1;
        return 0;
      });

      for (var index in keys) {
        var key = keys[index];
        if (typeof object[key] == "object" && !(object[key] instanceof Array)) {
          sortedObj[key] = sortObject(object[key]);
        } else {
          sortedObj[key] = object[key];
        }
      }

      return sortedObj;
    }

    function flatten(assets) {
      let flattenedAssets = Object.create(null, {});

      for (const namespace in assets) {
        if (namespace == "") {
          // const limbo = flatten(assets[namespace])
          // flattenedAssets = { ...flattenedAssets, ...limbo }
          // TODO: Implement
          continue;
        }

        for (const extension in assets[namespace]) {
          flattenedAssets[`${namespace}.${extension}`] =
            assets[namespace][extension];
        }
      }

      return flattenedAssets;
    }

    const sortedAssets = sortObject(assets);
    const flattenedAssets = flatten(sortedAssets);

    return JSON.stringify(flattenedAssets, null, 2);
  }
}