Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String replace plugin fails with Webpack 2.1 (2.1.0-beta.27) #20

Closed
mlcohen opened this issue Dec 12, 2016 · 5 comments
Closed

String replace plugin fails with Webpack 2.1 (2.1.0-beta.27) #20

mlcohen opened this issue Dec 12, 2016 · 5 comments

Comments

@mlcohen
Copy link

mlcohen commented Dec 12, 2016

I'm trying to upgrade my project from webpack 1.3 to webpack 2.1 (currently 2.1.0-beta.27). In my webpack configuration I'm making use of the string replace webpack plugin which works fine with webpack 1.3 but ends up causing a build error using webpack 2.1. Here is an example of what my config currently looks like with the string replace webpack plugin:

let StringReplacePlugin  = require('string-replace-webpack-plugin');

module.exports = {
    module: {
        rules: [{
            enforce: 'pre',
            test: /\.js$/,
            use: [{
                loader: StringReplacePlugin.replace({
                    pattern: /id="@(\w+):([\w\.]+)"/g,
                    replacement: function (match, p1, p2) {
                        return `id="${p2}" defaultMessage={${p1}.${p2}.message}`
                    }
                })
            }]
        },
        // .... other rules
       ]
    },

    plugins: [
        new StringReplacePlugin()
    ]
} 

And here is the build error that I'm getting:

ERROR in ./main.js
Module build failed: Error: Cannot find module '/Users/mlc/tmp/app/node_modules/string-replace-webpack-plugin/loader.js?id=n7if95dcsxmh55jdgfhpeewmi'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at loadLoader (/Users/mlc/tmp/app/node_modules/loader-runner/lib/loadLoader.js:13:17)
    at iteratePitchingLoaders (/Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:164:2)
    at iteratePitchingLoaders (/Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:160:10)
    at /Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:168:18
    at loadLoader (/Users/mlc/tmp/app/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:164:2)
    at iteratePitchingLoaders (/Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:160:10)
    at /Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:168:18
    at loadLoader (/Users/mlc/tmp/app/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:164:2)
    at runLoaders (/Users/mlc/tmp/app/node_modules/loader-runner/lib/LoaderRunner.js:357:2)
    at NormalModule.doBuild (/Users/mlc/tmp/app/node_modules/webpack/lib/NormalModule.js:131:2)
    at NormalModule.build (/Users/mlc/tmp/app/node_modules/webpack/lib/NormalModule.js:179:15)
    at Compilation.buildModule (/Users/mlc/tmp/app/node_modules/webpack/lib/Compilation.js:127:9)
    at Compilation.<anonymous> (/Users/mlc/tmp/app/node_modules/webpack/lib/Compilation.js:404:8)
    at /Users/mlc/tmp/app/node_modules/webpack/lib/NormalModuleFactory.js:74:13
    at NormalModuleFactory.applyPluginsAsyncWaterfall (/Users/mlc/tmp/app/node_modules/tapable/lib/Tapable.js:123:70)
    at onDoneResolving (/Users/mlc/tmp/app/node_modules/webpack/lib/NormalModuleFactory.js:49:11)
    at onDoneResolving (/Users/mlc/tmp/app/node_modules/webpack/lib/NormalModuleFactory.js:165:6)
    at /Users/mlc/tmp/app/node_modules/webpack/lib/NormalModuleFactory.js:161:6
    at /Users/mlc/tmp/app/node_modules/webpack/node_modules/async/dist/async.js:3694:9
    at /Users/mlc/tmp/app/node_modules/webpack/node_modules/async/dist/async.js:356:16
    at iteratorCallback (/Users/mlc/tmp/app/node_modules/webpack/node_modules/async/dist/async.js:936:13)
    at /Users/mlc/tmp/app/node_modules/webpack/node_modules/async/dist/async.js:840:16
    at /Users/mlc/tmp/app/node_modules/webpack/node_modules/async/dist/async.js:3691:13
    at apply (/Users/mlc/tmp/app/node_modules/webpack/node_modules/async/dist/async.js:21:25)

Any thoughts on how I can address this? Is there a simple fix that can be applied to my webpack config or is this a compatibility issue between the string replace plugin and webpack 2?

Code to reproduce the problem can be found here:

https://gist.github.com/mlcohen/6d338ce0494f5a2e966ef83474b3ab1b

other details

  • Node v6.9.1
  • macOS 10.12.1
@jamesandersen
Copy link
Owner

@mlcohen Hi there, I don't know of simple fix off the bat and am unfortunately a bit short on time to investigate just now. If you get to it before I do, a PR would be welcome.

@rayalan
Copy link

rayalan commented Dec 17, 2016

I came across this tonight and investigated it a little bit. It looks like something about the way loaders are returned has changed (e.g. no more passing back a random id in the query string). So the immediate problem is that if one tacks on ?id=..., webpack can't find the loader to call it.

The subsequent problem is that as soon as one stops returning the id, one can't find the original options any more when the loader is called. I suspect that webpack2 redid the loader interface and it would be trivial to fix if the new interface was documented/familiar to someone...unfortunately, that isn't me.

@mlcohen
Copy link
Author

mlcohen commented Dec 18, 2016

I finally figured it out. After some searching I came across this raised issue: webpack-contrib#275. Turns out that you can't currently use the new use webpack2 config syntax for plugins like the extract text webpack plugin, which is also the case for the string replace plugin. Instead of use, apply the loader syntax, like so:

module: {
    rules: [{
        enforce: "pre",
        test: /\.js$/,
        exclude: /node_modules/,
        loader: StringReplacePlugin.replace({
            replacements: [{
                pattern: /id="@(\w+):([\w\.]+)"/g,
                replacement: function (match, p1, p2) {
                    return `id="${p2}" defaultMessage={${p1}.${p2}.message}`
                }
            }]
        })
    }
}

I went back over the webpack2 docs and it does indeed show ExtractTextPlugin being applied to loader within the list of rules. I'm not sure if this subtle distinction is intended, but if it is, it would be really nice if the docs would clarify when to apply use and when to only apply loader. In any case, I can now build with the string replace plugin even with the latest version of webpack2 (v2.2.0-rc.1).

@RomanHotsiy
Copy link

On the latest webpack 2.2.0-rc.4 both syntaxes work fine for me:

loader: StringReplacePlugin.replace({...

and

rules: [{
  enforce: 'pre',
  test: /\.js$/,
  use: [{
    loader: StringReplacePlugin.replace({...

So maybe this issue should be closed

@mlcohen
Copy link
Author

mlcohen commented Jan 17, 2017

@RomanGotsiy Excellent. Thanks for the info 👍🏼

@mlcohen mlcohen closed this as completed Jan 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants