Skip to content

Loader can't modify resource type without accessing private API #7057

Closed

Description

@cletusw

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Now that webpack has the concept of module type (JSON, JS, CSS, WASM), loaders which convert resources from one type to another do not work without either requiring the end user to modify their config (i.e. for a loader that converts to JS the user must add type: 'javascript/auto' to their config) or resorting to modifying private internal webpack APIs. The former leaks internal loader implementation details onto the user and doesn't work if the user wants to pipe the output of that loader into another, while the latter is brittle and prone to breakage in future webpack versions.

See #6572 (comment), #6586, #6725, webpack-contrib/file-loader#264, webpack-contrib/file-loader#259, webpack-contrib/bundle-loader#74

If the current behavior is a bug, please provide the steps to reproduce.
Contrived example: https://github.com/cletusw/webpack-issue-7057

What is the expected behavior?
Webpack should support loaders that convert between resource types, probably via the loader API.

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.
Node v8.11.0
webpack 4.5.0
Linux

Activity

  1. changed the title [-]Loader can[/-] [+]Loader can't modify resource type without accessing private API[/+] on Apr 16, 2018
  2. added 2 commits that reference this issue on Apr 16, 2018
  3. sokra commented on Apr 17, 2018

    @sokra
    Member

    Makes sense. Maybe a this.setModuleType("javascript/auto") in the loader API.

    Do you want to send a PR? Note that module type set by loader should not leak between rebuilds. It need to be reset on unbuild.

  4. added a commit that references this issue on May 29, 2018
  5. added a commit that references this issue on Jul 2, 2018
  6. webpack-bot commented on Mar 1, 2019

    @webpack-bot
    Contributor

    This issue had no activity for at least half a year.

    It's subject to automatic issue closing if there is no activity in the next 15 days.

  7. added
    status: staleNo author response after a needs: request; close candidate
    on Mar 1, 2019
  8. alexander-akait commented on Mar 1, 2019

    @alexander-akait
    Member

    Bump

  9. removed
    status: staleNo author response after a needs: request; close candidate
    on Mar 1, 2019
  10. webpack-bot commented on Sep 7, 2019

    @webpack-bot
    Contributor

    This issue had no activity for at least half a year.

    It's subject to automatic issue closing if there is no activity in the next 15 days.

  11. added
    status: staleNo author response after a needs: request; close candidate
    on Sep 7, 2019
  12. alexander-akait commented on Sep 7, 2019

    @alexander-akait
    Member

    bump

  13. 2 remaining items

  14. added
    status: staleNo author response after a needs: request; close candidate
    on Dec 7, 2019
  15. Lyrkan commented on Dec 8, 2019

    @Lyrkan
    Contributor

    Bump so it doesn't get closed

    I tried adding the new method here: #10097

  16. removed
    status: staleNo author response after a needs: request; close candidate
    on Dec 8, 2019
  17. added
    status: staleNo author response after a needs: request; close candidate
    on Mar 9, 2020
  18. webpack-bot commented on Mar 24, 2020

    @webpack-bot
    Contributor

    Issue was closed because of inactivity.

    If you think this is still a valid issue, please file a new issue with additional information.

  19. removed
    status: staleNo author response after a needs: request; close candidate
    on Mar 25, 2020
  20. Lyrkan commented on Mar 25, 2020

    @Lyrkan
    Contributor

    @evilebottnawi I think it can be closed based on @sokra's comment here: #10097 (comment)

  21. alexander-akait commented on Mar 25, 2020

    @alexander-akait
    Member

    Yes, you are right, in webpack@5 it is possible to achieve that using plugin (you can look on asset or json plugin)

  22. ScriptedAlchemy commented on Jul 8, 2020

    @ScriptedAlchemy
    Contributor

    @Lyrkan @evilebottnawi
    Im wondering if you might be able to provide a hint here. Im attempting to upgrade the translation loader used at my company- which mentioned this git issue.

    The error getting thrown in Webpack 5 is as followed

    Module parse failed: Abstract method Parser.parse. Must be overridden.
    File was processed with these loaders:
     * ./loaders/lingui.js
    

    https://gist.github.com/ScriptedAlchemy/4d3f8e63d16d9b9150e30e8083d91048

    It sounds like I need to replace the this._module.parser with another one? Does anyone have any hints on how I could achieve this?

    The likely code in question is

    
      // Webpack 4 uses json-loader automatically, which breaks this loader because it
      // doesn't return JSON, but JS module. This is a temporary workaround before
      // official API is added (https://github.com/webpack/webpack/issues/7057#issuecomment-381883220)
      // See https://github.com/webpack/webpack/issues/7057
      if (JavascriptParser && JavascriptGenerator) {
        this._module.type = "javascript/auto";
        this._module.parser = new JavascriptParser();
        this._module.generator = new JavascriptGenerator();
      }
    
  23. Lyrkan commented on Jul 9, 2020

    @Lyrkan
    Contributor

    @ScriptedAlchemy I haven't tested it with the latest version of Webpack 5 but it worked a while ago:

    const LoaderDependency = require('webpack/lib/dependencies/LoaderDependency');
    
    const requiredType = 'javascript/auto';
    if (this._module.type !== requiredType) {
        // Try to retrieve the factory used by the LoaderDependency type
        // which should be the NormalModuleFactory.
        const factory = this._compilation.dependencyFactories.get(LoaderDependency);
        if (factory === undefined) {
            throw new Error('Could not retrieve module factory for type LoaderDependency');
        }
    
        this._module.type = requiredType;
        this._module.generator = factory.getGenerator(requiredType);
        this._module.parser = factory.getParser(requiredType);
    }
  24. ScriptedAlchemy commented on Jul 9, 2020

    @ScriptedAlchemy
    Contributor

    @Lyrkan thank youuuuuuuu ill try this out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedMaintainers welcome a community PR for this

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions