core icon indicating copy to clipboard operation
core copied to clipboard

Loader query function, regex, and object, support

Open colelawrence opened this issue 10 years ago • 5 comments

Currently, the loader query only supports strings, and when you pass it an actual object, it applies stringify to it, and prevents the ability to pass a function, which may be desirable if you wish to pass a custom minification function, or a regex to your loader.

Query to json string in /lib/LoadersList.js#L52-L61

function getLoadersFromObject(element) {
    if(element.query) {
        if(!element.loader || element.loader.indexOf("!") >= 0) throw new Error("Cannot define 'query' and multiple loaders in loaders list");
        if(typeof element.query === "string") return [element.loader + "?" + element.query];
        return [element.loader + "?" + JSON.stringify(element.query)];
    }
    if(element.loader) return element.loader.split("!");
    if(element.loaders) return element.loaders;
    throw new Error("Element from loaders list should have one of the fields 'loader' or 'loaders'");
}

jade-locals interpretting query: webpack/jade-loader/index.js#L9-L20

module.exports = function(source) {
    this.cacheable && this.cacheable();
    var jade = require("jade");

    var utils = require("jade/lib/utils");
    var nodes = require("jade/lib/nodes");
    var filters = require("jade/lib/filters");

    var req = loaderUtils.getRemainingRequest(this).replace(/^!/, "");

    var query = loaderUtils.parseQuery(this.query);

It is especially relevant for my current project where we need to pass in a localization function (convert keys to text) into the jade-loader locals object.

I feel this can be addressed by allowing element.query to be either an object or a string.

Maybe there is a way to work around this by allowing the list of loaders to be objects of the modules themselves, as described in webpack/How to register a custom loader in webpack.config #903 or where is apply-loader to use with jade-loader #940

colelawrence avatar Jul 09 '15 19:07 colelawrence

My config kinda looks like this:


  module: {
    loaders: [
      { test: /\.jsx?$/, loader: "ng-annotate-loader!babel-loader?stage=0", exclude: /web_modules|node_modules|bower_components/ },
      { test: /\.jade$/, loader: "jade-loader",
        query: {
          root: jadeOpts.basedir,
          locals: {
            localize: function (translation_key) {
              return translation_table[translation_key]
            }
          }
        }
      },

colelawrence avatar Jul 09 '15 19:07 colelawrence

I think I'm onto a really simple solution with:

  resolveLoader: {
    alias: {
      "jade-loader-wrapper": path.join(__dirname, "./jade-loader-wrapper")
    }
  },

Edit: To quickly fix my specific scenario, I had to copy and paste the jade-loader/index.js and jade-loader/stringify.loader.js into my project directory where jade-loader-wrapper resolves to and hard-code configure it to use the local variables and functions I needed.

colelawrence avatar Jul 09 '15 19:07 colelawrence

Actually, this makes sense why jade locals can only be in json, because the default locals need to be transferred to the client's browser, for when you render the jade client-side with additional locals. However, in my case, (using this with angular templates) I modified my custom jade-loader to return the string of HTML using just jade.render with no special features.


  run();
  function run() {
    var string;
    if (query.renderHTML) {
      string = jade.render(source, {
        filename: req,
        self: query.self,
        pretty: query.pretty,
        basedir: jadeCommon.jadeOpts.basedir,
        locals: jadeCommon.jadeOpts.locals,
        compileDebug: loaderContext.debug || false
      });
    } else {
      try {
        var tmplFunc = jade.compileClient(source, {
          parser: loadModule ? MyParser : undefined,

ref original webpack/jade-loader/index#L165-L172

colelawrence avatar Jul 09 '15 20:07 colelawrence

This would be nice to have this in core. No need to stringify something that loader developer will consume as an object. Are you open for a PR to allow query to be a (real) object @sokra ?

MoOx avatar Mar 18 '16 19:03 MoOx

@MoOx webpack/core is decrapted in webpack@2

thangngoc89 avatar Mar 18 '16 19:03 thangngoc89