Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

window is not defined using Angular4 + AoT + Webpack2

I have an angular4 app that uses webpack and has been working great with JiT but now I'm trying to get it working with AoT and I'm having issues. Specifically I'm getting the following error:

ERROR in window is not defined

ERROR in ./src/app/main/main.ts
Module not found: Error: Can't resolve './../../../aot-main/src/app/main/app.module.ngfactory' in 'W:\<Full Path to App>\src\app\main'
resolve './../../../aot-main/src/app/main/app.module.ngfactory' in 'W:\<Full Path to App>\src\app\main'
  using description file: W:\<Full Path to App>\package.json (relative path: ./src/app/main)
    Field 'browser' doesn't contain a valid alias configuration
  after using description file: W:\<Full Path to App>\package.json (relative path: ./src/app/main)
    using description file: W:\<Full Path to App>\package.json (relative path: ./aot-main/src/app/main/app.module.ngfactory)
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory doesn't exist
      .ts
        Field 'browser' doesn't contain a valid alias configuration
        W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory.ts doesn't exist
      .js
        Field 'browser' doesn't contain a valid alias configuration
        W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory.js doesn't exist
      as directory
        W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory doesn't exist
[W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory]
[W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory.ts]
[W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory.js]
[W:\<Full Path to App>\aot-main\src\app\main\app.module.ngfactory]
 @ ./src/app/main/main.ts 3:0-91

Assuming that the first line was due to the use of the global "window" variable I went through and replaced every reference to it with a service reference:

import { Injectable } from '@angular/core';

function getWindow(): any {
    return window;
}

@Injectable()
export class WindowRefService {
    get nativeWindow(): any {
        return getWindow();
    }
}

I'm pretty sure I got all of the places where I'm using the window variable but I can't get past the error and the information provided with the error seems marginally useless as it doesn't tell me where it's having the issue.

Here's my webpack config file:

var webpack = require('webpack');
var ngToolsWebpack = require('@ngtools/webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var helpers = require('./helpers');
require('es6-promise').polyfill();

module.exports = {
    entry: {
        MyApp: './src/app/main/main.ts',
        polyfills: './src/app/main/polyfills.ts',
        vendor: './src/app/main/vendor.ts'
    },
    resolve: {
        extensions: ['.ts', '.js']
    },
    output: {
        path: helpers.root('app'),
        publicPath: 'https://localhost:8080/app/',
        filename: 'js/[name].js?[hash]',
        chunkFilename: 'js/MyApp-[id].chunk.js?[hash]'
    },
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: [{ loader: '@ngtools/webpack' }, { loader: 'angular-router-loader' }]
            },
            {   test: /\.html$/,
                use: [{ loader: 'html-loader' }]
            },
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                use: [{ loader: 'file-loader?name=images/[name].[ext]' }]
            },
            {
                test: /\.scss$/,
                use: ['to-string-loader', 'style-loader', 'css-loader?sourceMap', 'sass-loader?sourceMap']
            }
        ]
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: ['MyApp', 'vendor', 'polyfills']
        }),
        new HtmlWebpackPlugin({
            template: 'src/app/main/index.html'
        }),
        new webpack.ContextReplacementPlugin(
            /angular(\\|\/)core(\\|\/)@angular/,
            helpers.root('doesnotexist')
        ),
        new ngToolsWebpack.AotPlugin({
            tsConfigPath: './tsconfig.main.aot.json',
            entryModule: './src/app/main/app.module#AppModule'
        })
    ]
};

Is there a way to better identify what is actually causing it to fail?

UPDATE 7/19/2017: I found that if I change the .scss loader in the webpack config to the following (and remove the angular-router-loader from the .ts rule) then I get it to compile but my styles don't show up:

use: ['raw-loader', 'sass-loader?sourceMap']

As soon as I add one of the other loaders in the error returns. Any idea how to get my .scss styles to show up?

like image 829
Gary Lapointe Avatar asked Jul 17 '17 23:07

Gary Lapointe


1 Answers

This may be a little late but I recently ran across this exact same issue and found the solution and I must say...holy guacamole is the error ERROR in window is not defined misleading!

The root cause? Style-loader. It appears that style-loader can only be built client-side (or locally). When you try to do AOT builds, it acts like a server-side build and it fails due to this issue: https://github.com/webpack-contrib/style-loader/issues/109

The solution? Replace style-loader with iso-morphic-style-loader: https://github.com/creeperyang/iso-morphic-style-loader

{
    test: /\.scss$/,
    use: ['to-string-loader', 'iso-morphic-style-loader', 'css-loader?sourceMap', 'sass-loader?sourceMap']
}
like image 73
CodeCheshire Avatar answered Nov 15 '22 06:11

CodeCheshire