Angular-cli: @ngtools/webpack impossible to pre-chain other loaders

Created on 14 Dec 2017  Â·  13Comments  Â·  Source: angular/angular-cli

The use of the webpack compiler host to get file source, here:
https://github.com/angular/angular-cli/blob/eb4c9e72ed09c6b544f2dddd038099cfb6d914c8/packages/%40ngtools/webpack/src/angular_compiler_plugin.ts#L831

rather than using the, maybe _changed-by-some-other-loader_ ヽ༼ ಠ益ಠ ༽ノ ?!! source, here:
https://github.com/angular/angular-cli/blob/eb4c9e72ed09c6b544f2dddd038099cfb6d914c8/packages/%40ngtools/webpack/src/loader.ts#L548

does not allow using other loaders before yours!

2 (required) broken

All 13 comments

+1
I'm having a problem with pre-chaining, described HERE.
I believe this is the same issue.

yeah, pretty much the same. the code is obvious

Damn, I wasted so much time tinkering with string-replace-loader, blaming it from not working properly, only to find out that this plugin is overriding everything what poor string-replace-loader did. Until this is fixed we probably won't be able to use AoT :disappointed:.

Same Problem Here!
As a quick work around I'm using an inverted loader order.
But beware: the source you are working on is already transformed, so maybe your loader did not see the file it expects...
I vote for fixing this problem!

@gerhard17 Can you provide a sample of your workaround? I couldn't get AoT to pick up replacements, regardless of the order.

Hi zolakt!

I had a very simple use case:
I want to replace all occurences from a function call to $stringify(SomeComponent) with "SomeComponent".
The purpose is to get a refactoring safe Component Name at runtime, even when UglifyJsPlugin shrinks function (constructor) names. (keep_fnames: false)

In WebPack-JIT I used:

{
    test: /\.ts$/,
    use: [
    {
        loader: 'awesome-typescript-loader',
        options: {
            "configFileName": tsConfigPath
        }
    },
    'angular2-template-loader',
    'angular-router-loader',
    {
        // Webpack smart-replace-loader 
        // Author: Gerhard
        // Works simmilar to string-replace-loader (options and regex)
        loader: './extensions/smart-replace-loader',
        options: {
            multiple: [
                {
                    search: /\$stringify\(\s*([A-Za-z_$][A-Za-z0-9_$]*)\s*\)/g,
                    replace: '"$1"'
                },...
            ]
        }
    }
    ]
},

Moving to WebPack-AOT I transformed it (not working) to:

{
    test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
    use: [
    {
        loader: '@ngtools/webpack'
    }
    //BUG loader not chainable: https://github.com/angular/angular-cli/issues/8870
    {
        // Webpack smart-replace-loader 
        // Author: Gerhard
        // Works simmilar to string-replace-loader (options and regex)
        loader: './extensions/smart-replace-loader',
        options: {
            multiple: [
                {
                    search: /\$stringify\s*\(\s*([A-Za-z_$][A-Za-z0-9_$]*)\s*\)/g,
                    replace: '"$1"'
                },...
            ]
        }
    }
    ]
},

So I swapped the loader order (as a quick fix).
BUT I HAD TO CHANGE THE SEARCH STRING!
Because it's not the original TypeScript file the smart-replace-loader operates on.
It's operating on an already transformed JavaScript file, which is a mess!

The resulting loader configuration:

{
    test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
    use: [
    {
        // Webpack smart-replace-loader 
        // Author: Gerhard
        // Works simmilar to string-replace-loader (options and regex)
        loader: './extensions/smart-replace-loader',
        options: {
            multiple: [
                {
                    //search: /\$stringify\s*\(\s*([A-Za-z_$][A-Za-z0-9_$]*)\s*\)/g,
                    search: /\$stringify\s*\(\s*(?:[A-Za-z_$][A-Za-z0-9_$]*\.)*([A-Za-z_$][A-Za-z0-9_$]*)\s*\)/g,
                    replace: '"$1"'
                },...
            ]
        }
    },
    //BUG loader not chainable: https://github.com/angular/angular-cli/issues/8870
    {
        loader: '@ngtools/webpack'
    }
    ]
},

Hope this helps!
Regards, Gerhard

Having similar issues. Voting for this to be fixed.

Any updates?

My guess is that ngtools internally executes ngc, which is not a part of webpack flow and effectively ignores all the changes previous loaders have made to our precious .ts files.

Here's my solution someone might find useful. I needed to make some changes to a dictionary file. It didn't have anything ng-specific in it, so I just excluded it from ngtools scope. And added a rule to compile it with ts-loader after my custom loader finishes.

[ { test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, exclude: [/\.(spec|e2e|d)\.ts$/, path.resolve(dirs.config, 'client-context.ts')], use: '@ngtools/webpack' }, { test: /client-context\.ts$/, include: path.join(dirs.config), use: [ 'ts-loader', 'client-context-loader' ] };

This way I get client-context module processed by my loader, compiled by ts-loader and bundled by webpack.

@elimin8r we'll discuss it during our next triage in 2019, sorry for the late response.

This is working as intended at the moment.

After one year of thinking...
Short comment : Sad decission!

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

delasteve picture delasteve  Â·  3Comments

gotschmarcel picture gotschmarcel  Â·  3Comments

MateenKadwaikar picture MateenKadwaikar  Â·  3Comments

brtnshrdr picture brtnshrdr  Â·  3Comments

sysmat picture sysmat  Â·  3Comments