webpack / core

[OBSOLETE in webpack 2] The core of webpack and enhanced-require...
26 stars 26 forks source link

Loader query function, regex, and object, support #13

Open colelawrence opened 9 years ago

colelawrence commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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

MoOx commented 8 years ago

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 ?

thangngoc89 commented 8 years ago

@MoOx webpack/core is decrapted in webpack@2