1
votes

I understand that the difference between building with webpack and webpack-dev-server is that the latter outputs and serves from memory and the former creates the output to disk and doesn't spin up Express to serve it.

My issue is that my webpack config works fine if I run it through webpack, then run webpack-dev-server, but with the latter watching it, when changes are made, they're not reflected in the output (as expected since it's supposed to just impact what's in memory). However, if I delete the built files on disk and don't bundle with webpack first, I cannot get webpack-dev-server to load the Angular app (page is blank and says "Cannot GET /").

Semi-Working Approach

This works (but isn't ideal because I'm building it all twice):

  • Create a webpack config with the output and devserver options specified.
  • Run the npm command "npm run webpack -- --config appConfigs/webpack.dev.js --progress --profile && npm run webpack-dev-server -- --config appConfigs/webpack.dev.js --open --progress --profile --inline"
  • It builds to the output directory, then webpack-dev-server launches those files and it runs without a hitch.

Using only webpack-dev-server

This doesn't seem right. The whole point of webpack-dev-server is to serve from memory, so it shouldn't need to read from the output file at all. If I do the following, it doesn't work though:

  • Delete the previously generated output folder.
  • Run the npm command "npm run webpack-dev-server -- --config appConfigs/webpack.dev.js --open --progress --profile --inline"
  • When the browser loads up, greeted with error "Cannot GET /"

Here's what webpack-dev-server outputs with regards to where content is located at: Project is running at http://localhost:9000/ webpack output is served from / Content not from webpack is served from C:\xyz\dist

So, I would expect that when it loads up, it'd find the index.html at http://localhost:9000, but I get "Cannot GET /" instead.

Now, another SO post indicated that because no files are written, I needed to use a plugin like HtmlWebpackPlugin to ensure that it was properly created and available to webpack, but that doesn't appear to have resolved the issue.

webpack.dev.config Contents

Here's my webpack.dev.config (note that this file works fine if I bundle normally with webpack, and serves fine if I bundle with webpack, then run webpack-dev-server).

const webpack = require('webpack');
const helpers = require('./helpers');

const DefinePlugin = require('webpack/lib/DefinePlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');

/**
 * Webpack constants
*/
const ENV = process.env.ENV = process.env.NODE_END = 'development';
const HOST = 'localhost';
const PORT = 3000;
const PUBLIC = process.env.PUBLIC || undefined;
const HMR = helpers.hasProcessFlag('hot');
const METADATA = {
    host: HOST,
    port: PORT,
    public: PUBLIC,
    ENV: ENV,
    HMR: HMR
};

module.exports = {
    devtool: 'cheap-module-source-map',

    performance: {
        hints: false
    },

    entry: {
        'polyfills': helpers.root('src', 'polyfills.browser.ts'),
        'app': helpers.root('src', 'main.browser.ts')
    },

    output: {
        path: helpers.root('dist'),
        filename: 'js/[name].bundle.js',
        chunkFilename: 'js/[id].chunk.js',
        sourceMapFilename: '[file].map',
        publicPath: '/'
    },

    devServer: {
        historyApiFallback: true,
        contentBase: helpers.root('dist'),
        port: 9000
    },

    resolve: {
        extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html']
    },

    module: {
        rules: [
            {
                test: /\.ts$/,
                use: [
                        {
                            loader: 'awesome-typescript-loader',
                            options: {
                                configFileName: 'tsconfig.webpack.json'
                            }
                        },
                        'angular-router-loader',
                        'angular2-template-loader',
                        {
                            loader: 'tslint-loader',
                            options: {
                                conigFile: 'tslint.json'
                            }
                        },
                        'source-map-loader'
                ],
                exclude: [/\.(spec|e2e)\.ts$/]
            },
            {
                test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/,
                loader: 'file-loader?name=assets/[name]-[hash:6].[ext]'
            },
            {
                test: /\.json$/,
                loader: 'json-loader'
            },
            {
                test: /favicon.ico$/,
                loader: 'file-loader?name=/[name].[ext]'
            },
            {
                test: /\.scss$/,
                loaders: ["style-loader", "css-loader", "sass-loader"]
            },
            {
                test: /\.html$/,
                loader: ['html-loader'],
            }
        ],
        exprContextCritical: false
    },
    plugins: [
        new DefinePlugin({
            'ENV': JSON.stringify(METADATA.ENV),
            'HMR': METADATA.HMR, //unused here
            'process.env': {
                'ENV': JSON.stringify(METADATA.ENV),
                'NODE_ENV': JSON.stringify(METADATA.ENV),
                'HMR': METADATA.HMR //unused here
            }
        }),
        new LoaderOptionsPlugin({
            debug: true,
            options: {
            }
        }),
        new webpack.ContextReplacementPlugin(
            /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
            helpers.root('src'),
            {}
        ),
        new webpack.optimize.CommonsChunkPlugin({
            name: ['app', 'polyfills'],
            minChunks: Infinity
        }),
        new HtmlWebpackPlugin({
            inject: 'body',
            template: './src/index.html'
        })
    ]
};

(Partial) Output from webpack-dev-server

Limited for brevity

10% building modules 2/2 modules 0 active
Project is running at http://localhost:9000/
webpack output is served from /
Content not from webpack is served from C:\xyz\dist
404s will fallback to /index.html
...
Hash: 8ccd65a6efa15f3c1590
Version: webpack 3.5.1
Time: 29663ms
                     Asset     Size  Chunks                    Chunk Names
          js/app.bundle.js   4.6 MB       0  [emitted]  [big]  app
    js/polyfills.bundle.js   577 kB       1  [emitted]  [big]  polyfills
      js/app.bundle.js.map  4.97 MB       0  [emitted]         app
js/polyfills.bundle.js.map   691 kB       1  [emitted]         polyfills
                index.html  1.14 kB          [emitted]
 [560] (webpack)-dev-server/client?http://localhost:9000 5.83 kB {1} [built]
       [] -> factory:77ms building:65ms = 142ms
 [747] multi (webpack)-dev-server/client?http://localhost:9000 ./src/polyfills.browser.ts 40 bytes {1} [built]
        factory:0ms building:3ms = 3ms
 [756] ./node_modules/loglevel/lib/loglevel.js 6.74 kB {1} [built]
       [] -> factory:6700ms building:254ms = 6954ms
 [757] (webpack)-dev-server/client/socket.js 856 bytes {1} [built]
       [] -> factory:34ms building:757ms = 791ms
 [789] (webpack)-dev-server/client/overlay.js 3.6 kB {1} [built]
       [] -> factory:36ms building:743ms = 779ms
 [794] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {1} [built]
       [] -> factory:31ms building:14ms = 45ms
 [796] (webpack)/hot/emitter.js 77 bytes {1} [built]
       [] -> factory:6257ms building:24ms = 6281ms
 [798] ./src/polyfills.browser.ts 1.16 kB {1} [built]
       [] -> factory:188ms building:6063ms = 6251ms
 [799] ./node_modules/core-js/es6/regexp.js 346 bytes {1} [built]
       [] -> factory:551ms building:50ms = 601ms
 [806] ./node_modules/core-js/es6/map.js 208 bytes {1} [built]
       [] -> factory:552ms building:55ms dependencies:4419ms = 5026ms
 [812] ./node_modules/core-js/es6/set.js 208 bytes {1} [built]
       [] -> factory:552ms building:53ms dependencies:4416ms = 5021ms
 [813] ./node_modules/core-js/es6/weak-map.js 176 bytes {1} [built]
       [] -> factory:553ms building:56ms dependencies:4415ms = 5024ms
 [864] multi (webpack)-dev-server/client?http://localhost:9000 ./src/main.browser.ts 40 bytes {0} [built]
        factory:0ms building:2ms dependencies:78ms = 80ms
 [865] ./src/main.browser.ts 899 bytes {0} [built]
       [] -> factory:452ms building:5896ms = 6348ms
[1436] ./src/app/environment.ts 1.01 kB {0} [built]
       [] -> factory:61ms building:106ms = 167ms
    + 1422 hidden modules
Child html-webpack-plugin for "index.html":
     1 asset
       [0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html 1.18 kB {0} [built]
            factory:476ms building:5898ms = 6374ms
webpack: Compiled successfully.

So, it looks like it works, but I cannot navigate to anything with getting "Cannot GET {whatever I tried to go to}"

In the meantime, I can run the semi-working approach, but it'll bundle it via webpack, output to the directory, then launch the webpack-dev-server from files in that directory, which isn't what it seems like it should be doing (this takes twice as long because it bundles twice).

What am I missing?

1

1 Answers

0
votes

Deleted node_modules and reinstalled everything using yarn and it's working exactly as advertised. Not sure what's different, but no further issue here.