Giter VIP home page Giter VIP logo

koa-webpack's Introduction

koa-webpack

tests cover size

Development and Hot Module Reload Middleware for Koa2, in a single middleware module.

This module wraps and composes webpack-dev-middleware and webpack-hot-client into a single middleware module, allowing for quick and concise implementation.

As an added bonus, it'll also use the installed webpack module from your project, and the webpack.config.js file in the root of your project, automagically, should you choose to let it. This negates the need for all of the repetitive setup and config that you get with koa-webpack-middleware.

Install

Using npm:

npm install koa-webpack --save-dev

Requirements

koa-webpack is an evergreen module. ๐ŸŒฒ This module requires an Active LTS Node version (v8.0.0+ or v10.0.0+), and Webpack v4.0.0+.

Usage

const Koa = require('koa');
const koaWebpack = require('koa-webpack');

const app = new Koa();
const options = { .. };
const middleware = await koaWebpack(options);

app.use(middleware);

API

koaWebpack([options])

Returns a Promise which resolves the server middleware containing the following additional properties:

  • close(callback) (Function) - Closes both the instance of webpack-dev-middleware and webpack-hot-client. Accepts a single Function callback parameter that is executed when complete.
  • hotClient (Object) - An instance of webpack-hot-client.
  • devMiddleware (Object) - An instance of webpack-dev-middleware

Options

The middleware accepts an options Object, which can contain options for the webpack-dev-middleware and webpack-hot-client bundled with this module. The following is a property reference for the Object:

compiler

Type: Object
optional

Should you rather that the middleware use an instance of webpack that you've already init'd [with webpack config], you can pass it to the middleware using this option.

Example:

const webpack = require('webpack');
const config = require('./webpack.config.js');
const koaWebpack = require('koa-webpack');

const compiler = webpack(config);
const middleware = await koaWebpack({ compiler });

app.use(middleware);

config

Type: Object

Should you rather that the middleware use an instance of webpack configuration that you've already required/imported, you can pass it to the middleware using this option.

Example:

const koaWebpack = require('koa-webpack');
const config = require('./webpack.config.js');

const middleware = await koaWebpack({ config });

app.use(middleware);

configPath

Type: String

Allows you to specify the absolute path to the Webpack config file to be used.

Example:

const path = require('path');
const koaWebpack = require('koa-webpack');

// The Webpack config file would be at "./client/webpack.config.js".
const middleware = await koaWebpack({
  configPath: path.join(__dirname, 'client', 'webpack.config.js')
});

app.use(middleware);

devMiddleware

Type: Object

The devMiddleware property should contain options for webpack-dev-middleware, a list of which is available at webpack-dev-middleware. Omitting this property will result in webpack-dev-middleware using its default options.

hotClient

Type: Object|Boolean

The hotClient property should contain options for webpack-hot-client, a list of which is available at webpack-hot-client. Omitting this property will result in webpack-hot-client using its default options.

As of v3.0.1 setting this to false will completely disable webpack-hot-client and all automatic Hot Module Replacement functionality.

Using with koa-compress

When using koa-webpack with koa-compress, you may experience issues with saving files and hot module reload. Please review this issue for more information and a workaround.

Server-Side-Rendering

When serverSideRender is set to true in config.devMiddleware, webpackStats is accessible from ctx.state.webpackStats.

app.use(async (ctx, next) => {
  const assetsByChunkName = ctx.state.webpackStats.toJson().assetsByChunkName;
  // do something with assetsByChunkName
})

For more details please refer to: webpack-dev-middleware

Using with html-webpack-plugin

When using with html-webpack-plugin, you can access dev-middleware in-memory filesystem to serve index.html file:

const middleware = await koaWebpack({ config });

app.use(middleware);

app.use(async (ctx) => {
  const filename = path.resolve(webpackConfig.output.path, 'index.html')
  ctx.response.type = 'html'
  ctx.response.body = middleware.devMiddleware.fileSystem.createReadStream(filename)
});

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

Attribution

This module started as a fork of koa-webpack-middleware

License

koa-webpack's People

Contributors

af avatar antialias avatar avivahl avatar christensson avatar croissong avatar detrohutt avatar dpatti avatar dzcpy avatar greenkeeper[bot] avatar josser avatar jounqin avatar jqueryisamonad avatar kimjuny avatar lavatoaster avatar lostpebble avatar mike-marcacci avatar noinkling avatar olsonpm avatar pearofducks avatar reod avatar shellscape avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

koa-webpack's Issues

using ts-node reloading does not reflect any changes made in the app

I am unsure as to how to get this package working, either by using node or ts-node, so I've created a sample app/repo here:
https://github.com/jwldnr/koawebpack

This might not be the right place for this, but hopefully you can help me gain some clarity and this issue might help someone else in the future.

koawebpack

koa-webpack usage example

steps to reproduce

  • install dependencies using yarn
    -> cd koawebpack && yarn

  • compile using webpack, run app through node
    -> yarn use:node

ERROR in multi /src/App.ts
Module not found: Error: Can't resolve '/src/App.ts' in '/Users/m41n/source/repos/koawebpack'
 @ multi /src/App.ts app[0]
โ„น ๏ฝขwdm๏ฝฃ: Failed to compile.
  • use ts-node directly
    -> yarn use:ts-node

    App compiles ok, uses WDM.
    -> Browse to http://localhost:3000/ should display "hello world"
    -> Change body response in src/App.ts e.g. ctx.body = "hello updated world"
    -> terminal showing compile activity..
    .. then refresh http://localhost:3000/, still showing old response (not updated)

โ„น ๏ฝขhot๏ฝฃ: webpack: Bundle Invalidated
โ„น ๏ฝขwdm๏ฝฃ: Compiling...
โ„น ๏ฝขhot๏ฝฃ: webpack: Compiling...
โ„น ๏ฝขhot๏ฝฃ: webpack: Compiling Done
โ„น ๏ฝขwdm๏ฝฃ: Hash: a5292ae7e6ff2093ef76
Version: webpack 4.16.3
Time: 26ms
Built at: 07/31/2018 12:14:43 PM
 Asset      Size  Chunks  Chunk Names
app.js  31.5 KiB     app  app
Entrypoint app = app.js
[./src/App.ts] 1.14 KiB {app} [built]
[./webpack.config.ts] 905 bytes {app}
[koa] external "koa" 42 bytes {app}
[koa-webpack] external "koa-webpack" 42 bytes {app}
[path] external "path" 42 bytes {app}
[webpack] external "webpack" 42 bytes {app}
[webpack-node-externals] external "webpack-node-externals" 42 bytes {app}
[0] multi ./src/App.ts 28 bytes {app}
โ„น ๏ฝขwdm๏ฝฃ: Compiled successfully.
  • Node Version: 10.6.0
  • NPM Version: 6.1.0
  • koa Version: 2.5.2
  • koa-wepback Version: 5.1.0

Expected Behavior

when using koa-webpack to reload, it should reflect changes

Actual Behavior

compiles, but does not reflect changes

How can we reproduce the behavior?

use provided repo with the description above

TypeError: webpack-hot-client: `entry` Object values must be an Array.

The latest uses this "webpack-hot-client": "^1.0.1" which is over 2 years old. It produces this error which is due to buggy code in 1.0.1

TypeError: webpack-hot-client: `entry` Object values must be an Array. Please check your webpack config.
        at validateEntry (D:\myapp\node_modules\webpack-hot-client\lib\util.js:138:19)
        at module.exports (D:\myapp\node_modules\webpack-hot-client\index.js:26:3)
        at fn (D:\myapp\node_modules\koa-webpack\index.js:74:18)

My entry object:

 entry: [
    'babel-polyfill', // Support promise for IE browser (for dev)
    'react-hot-loader/patch',
    'webpack-hot-middleware/client?reload=true',
    './src/client.js'
  ]

In the latest webpack-hot-client, this check has been fixed.

Example

Hi! Can you add link to simple project on github with this middleware: koa2, webpack2 and React (for example, I can help with it). Yesterday I couldn't setup it together.

Setup CI

Note for myself to setup linting in CI for PRs and Pushes

Updates require multiple file saves

  • Node Version: v6.10.0
  • NPM Version: 3.10.10
  • koa Version: 2.0.1
  • koa-wepback Version: 0.3.1
// webpack.config.js
export default {
  entry: {
    head: [
      'webpack-hot-middleware/client',
      'babel-polyfill',
      `${APP}/entry.js`,
      `${STYLES}/main.scss`,
    ],
  },

Server integration:
https://github.com/tomatau/breko-hub/blob/koa2/src/helpers/hotReload.js#L24-L38

Actual Behavior

After making any file change, my server is logging

COMPILER DONE
webpack built a6f0726c3057b262a440 in 330ms
publish everyClient built

But sometimes the client logs nothing. However, if I repeatedly save the file (without changes), eventually my client will log

[HMR] bundle rebuilding
client.js?3ac5:207 [HMR] bundle rebuilt in 883ms
process-update.js?e13e:27 [HMR] Checking for updates on the server...

How can we reproduce the behavior?

Clone this branch on this boilerplate repository: https://github.com/tomatau/breko-hub/tree/koa2
Ensure you have a .env file with NODE_ENV=development. Enable the debugger (sensible defaults in example.env). Run npm start and make multiple file changes to any react component.

hot-reload Webpack compile started... +39s
  hot-reload Webpack compiling... +0ms
  hot-reload Clearing /app/ module cache from server +648ms
  hot-reload hot reloading server change /Users/tomatao/Projects/tomatao/js/breko-hub/src/server/webpack-assets.json +235ms
  hot-reload Webpack compile started... +2s
  hot-reload Webpack compiling... +1ms
  hot-reload Clearing /app/ module cache from server +285ms
  hot-reload hot reloading server change /Users/tomatao/Projects/tomatao/js/breko-hub/src/server/webpack-assets.json +133ms
  hot-reload Webpack compile started... +2s
  hot-reload Webpack compiling... +1ms
  hot-reload Clearing /app/ module cache from server +344ms
  <-- GET /1691eb07362da1beccb5.hot-update.json
  --> GET /1691eb07362da1beccb5.hot-update.json 200 1ms 43b
  <-- GET /0.1691eb07362da1beccb5.hot-update.js
  --> GET /0.1691eb07362da1beccb5.hot-update.js 200 2ms 8.03kb
  hot-reload hot reloading server change /Users/tomatao/Projects/tomatao/js/breko-hub/src/server/webpack-assets.json +126ms

You can see a "Webpack compile started..." for each file save, but only eventually does the request come through for the hot-update chunks.

Notes

Thanks for making this library. I originally tried koa-webpack-middleware but it was breaking mime types as the hot middleware set octetstream on every response.

My boilerplate (linked) was working fine in every way for hot reloading (even server side live updates and hot updates of css-modules). I have made the minimal changes to migrate to koa2 and debugging this issue has left me stumped. I have thrown logs all over webpack-hot-middlewares client middleware and server middleware and can see the server sending messages but the client only receiving a subset of them. Eventually if I CMD+S on my file enough times after making a change the client will update.

This may be a more appropriate issue for webpack-hot-middleware but that repository seems less responsive to issues.

Cannot set property 'webpackStats' of undefined

Node version: 7.5.0
NPM version: 4.1.2
Koa version: 2.0.0-alpha.7
koa-webpack version: 0.3.0

Error output: UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot set property 'webpackStats' of undefined

I'm getting this error when using the serverSideRender: true option in webpack-dev-middleware and a following middleware. I think it's caused by webpack-dev-middleware wanting to set res.locals.webpackStats here.
I believe the res object is created here and cannot be changed in between.

lazy: false is not working

When I setup lazy prop to false, it is stop working correct: webpack build bundle, but return error with 404 status

Module not found: Error: Can't resolve 'webpack-hot-client/client?

Everything else seems to be working fine, but the following error was reported. My entry is similar to this {
ย ย  Index:["index.ts"]
} In anxiety, I hope you can point me awry.
"webpack": "^4.14.0",
"webpack-cli": "^3.0.8",
"koa-webpack": "^5.0.2",
ERROR in multi webpack-hot-client/client?51a207ab-5368-4dd3-ae13-c976b884cece ./src/webapp/views/index/index-index.entry.ts
Module not found: Error: Can't resolve 'webpack-hot-client/client?51a207ab-5368-4dd3-ae13-c976b884cece' in '/Users/yuanzhijia/Desktop/childcode'
@ multi webpack-hot-client/client?51a207ab-5368-4dd3-ae13-c976b884cece ./src/webapp/views/index/index-index.entry.ts

Can't get to work

    "koa-webpack": "^0.3.1",
    "react-hot-loader": "next",
    "webpack-dev-server": "^2.4.1"
	entry: [
		'react-hot-loader/patch',
		// activate HMR for React

		'webpack-dev-server/client?/__webpack_hmr',
		// bundle the client for webpack-dev-server
		// and connect to the provided endpoint

		'webpack/hot/only-dev-server',
		// bundle the client for hot reloading
		// only- means to only hot reload for successful updates

		'./client/index.js',
	],
const middleware = koaWebpack({
	compiler
});

app.use(middleware);

Error:

abstract-xhr.js:132 GET http://localhost:1488/__webpack_hmr/info?t=1489273162796 404 (Not Found)

Hot reload does not seem to work with Angular

  • Node Version: 9.9.0
  • NPM Version: 5.6.0
  • koa Version: 2.5.1
  • koa-wepback Version: 4.0.0
// client/config/webpack.dev.js
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
var webpack = require('webpack');

module.exports = webpackMerge(commonConfig, {
    devtool: 'cheap-module-eval-source-map',
    mode: 'development',

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

    plugins: [
        new ExtractTextPlugin('[name].css'),
        new webpack.NamedModulesPlugin()
        //new webpack.HotModuleReplacementPlugin()
    ],

    devServer: {
        historyApiFallback: true,
        stats: 'minimal',
        hotOnly: true
    }

});
// client/src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';

import { AppModule } from './app/app.module';

declare var module: any;

if (process.env.ENV === 'production') {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);

if (module.hot) {
    module.hot.accept();
}
// server/server.js
const Koa = require('koa');
const app = new Koa();

const serve = require('koa-static');

const staticFiles = __dirname + '/../public/dist';
const opts = {};

if (app.env != 'production') {
    const webpack = require('webpack');
    const koaWebpack = require('koa-webpack');
    const webpackConfig = require('../client/config/webpack.dev');
    let compiler = webpack(webpackConfig);
    console.log(compiler.options.output);

    app.use(koaWebpack({compiler: compiler}));
}

app.listen(4000);
console.log('Listening port 4000.');

All these codes have been pushed to my repo: https://github.com/wuyuMk7/development-kits/tree/angular-koa

Expected Behavior

The page can be updated by HMR when its code is modified.

Actual Behavior

The hot module reloading does not work. Every time I modify my file, such as the stylesheet file, the client can receive the hot-update file and messages from the server but the page keeps unchanged.

screen shot 2018-05-30 at 4 55 51 pm

However, if I use webpack-dev-server and HotModuleReplacementPlugin instead of koa-webpack, the hot reloading works well. I am confused about that. I am not sure if the angular needs some extra configuration to work with the koa-webpack.

How can we reproduce the behavior?

Just run yarn dev and modify one file under client/src/app folder. Open the developer tools and you will see that the client can receive messages and files from the server but the page is not changed.

Thank you for your help.

need to update dependencies for webpack 3

  • Node Version: 8.1.3
  • NPM Version: 4.6.1
  • yarn Version: 0.27.3 (I use yarn)
  • koa Version: 2.3.0
  • koa-wepback Version: 0.5.1

I found that using the current version of koa-webpack will encounter the following error:

records.chunkModuleIds[chunk.id] = chunk.mapModules(function(m) {                  
                                         ^                  

TypeError: chunk.mapModules is not a function

After installing the latest webpack-dev-middleware and webpack-hot-middleware and
copying the entire index.js (from this project) into my code to substitute the original module, webpack works smoothly.

How can I use webpack html plugin in your koa-webpack

Hi @shellscape ,
in koa v1, I implement this webpack hot middleware as following:

  const webpack = require('webpack')
  const webpackConfig = require('../webpack/webpack.config.js')

  const compiler = webpack(webpackConfig)
  const middleware = require('webpack-dev-middleware')(compiler, {
    publicPath: webpackConfig.output.publicPath,
    contentBase: 'src',
    stats: {
      colors: true,
      hash: false,
      timings: true,
      chunks: false,
      chunkModules: false,
      modules: false
    }
  })

  app.use(middleware)
  const hotMiddleware = require('webpack-hot-middleware')(compiler)
  // force page reload when html-webpack-plugin template changes
  compiler.plugin('compilation', (compilation) => {
    compilation.plugin('html-webpack-plugin-after-emit', (data, cb) => {
      hotMiddleware.publish({ action: 'reload' })
      cb()
    })
  })
  app.use(hotMiddleware)

But now with your plugin, the hotMiddleware is not single export any more, how can i configure the event of html-webpack-plugin-after-emit ?

Thanks a lot

react hmr example

I'd love to see working example of koa-webpack with webpack 2 and react-hot-loader3

Incorrect check for publicPath

  • Node Version: 10.9.0
  • NPM Version: 6.4.1
  • koa Version: 2.6.2
  • koa-wepback Version: 5.1.1

Expected Behavior

Allow to have configured publicPath in the Webpack config to an empty string: publicPath: '';

Actual Behavior

It throws:
"koa-webpack: publicPath must be set on dev options, or in a compiler's output configuration."

How can we reproduce the behavior?

Configure webpack to have publicPath to an empty string.

The fix would be to do something like this in lib/index.js

if (!options.devMiddleware.publicPath) {
    const { publicPath } = compiler.options.output;

    if (typeof publicPath === 'undefined') {
      throw new Error(
        "koa-webpack: publicPath must be set on `dev` options, or in a compiler's `output` configuration."
      );
    }

    options.devMiddleware.publicPath = publicPath;
  }

Hot reloading doesn't work in 2.0

  • Node Version: 8.9.4
  • NPM Version: 5.2.0
  • koa Version: ^2.3.0
  • koa-webpack: ^2.0.3
v2 webpack.config
// webpack.config.js
'use strict' // eslint-disable-line

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { CSSModules, inlineLimit } = require('./config')

const nodeEnv = process.env.NODE_ENV || 'development'
const isDev = nodeEnv !== 'production'

const WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin')
const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('./WIT.config')).development(isDev)

// Setting the plugins for development/production
const getPlugins = () => {
  // Common
  const plugins = [
    new ExtractTextPlugin({
      filename: '[name].[contenthash:8].css',
      allChunks: true,
      disable: isDev, // Disable css extracting on development
      ignoreOrder: CSSModules
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        // Javascript lint
        eslint: {},
        context: '/', // Required for the sourceMap of css/sass loader
        debug: isDev,
        minimize: !isDev
      }
    }),
    // Style lint
    new StyleLintPlugin({ files: ['src/**/*.css'], quiet: false }),
    // Setup environment variables for client
    new webpack.EnvironmentPlugin({ NODE_ENV: JSON.stringify(nodeEnv) }),
    // Setup global variables for client
    new webpack.DefinePlugin({
      __CLIENT__: true,
      __SERVER__: false,
      __DEV__: isDev
    }),
    new webpack.NoEmitOnErrorsPlugin(),
    webpackIsomorphicToolsPlugin,
    new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: module => /node_modules/.test(module.resource) })
  ]

  if (isDev) {
    // For development
    plugins.push(
      // Prints more readable module names in the browser console on HMR updates
      new webpack.NamedModulesPlugin(),
      new webpack.IgnorePlugin(/webpack-stats\.json$/),
      new BundleAnalyzerPlugin({
        analyzerMode: 'static',
        openAnalyzer: false
      })
    )
  } else {
    plugins.push(
      // For production
      new webpack.HashedModuleIdsPlugin(),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        beautify: false,
        mangle: { screw_ie8: true },
        compress: {
          screw_ie8: true, // React doesn't support IE8
          warnings: false,
          unused: true,
          dead_code: true
        },
        output: { screw_ie8: true, comments: false }
      })
    )
  }

  return plugins
}

// get babel plugins for dev/production
const getBabelPlugins = () => {
  const plugins = [
    'react-hot-loader/babel',
    'transform-object-rest-spread',
    'transform-class-properties',
    [
      'transform-imports',
      {
        'redux-form': {
          transform: 'redux-form/es/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        },
        lodash: {
          transform: 'lodash/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        }
      }
    ]
  ]

  if (isDev) {
    plugins.push('transform-react-jsx-source')
  }

  return plugins
}

// Setting the entry for development/production
const getEntry = () => {
  // For development
  let entry = [
    'babel-polyfill', // Support promise for IE browser (for dev)
    'react-hot-loader/patch',
    './src/client.js'
  ]

  // For production
  if (!isDev) {
    entry = {
      main: './src/client.js'
    }
  }

  return entry
}

// Setting webpack config
module.exports = {
  name: 'client',
  target: 'web',
  cache: isDev,
  devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
  context: path.join(process.cwd()),
  entry: getEntry(),
  output: {
    path: path.join(process.cwd(), './build/public/assets'),
    publicPath: '/assets/',
    // Don't use chunkhash in development it will increase compilation time
    filename: isDev ? '[name].js' : '[name].[chunkhash:8].js',
    chunkFilename: isDev ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
    pathinfo: isDev
  },
  module: {
    noParse: [/dtrace-provider/, /safe-json-stringify/, /mv/, /source-map-support/],
    rules: [
      {
        test: /\.jsx?$/,
        enforce: 'pre',
        exclude: /node_modules/,
        loader: 'eslint',
        options: {
          fix: true
        }
      },
      {
        test: /node_modules[/\\]jsonstream/i,
        loader: 'shebang'
      },
      {
        test: /\.jsx?$/,
        loader: 'babel',
        exclude: /node_modules/,
        options: {
          cacheDirectory: isDev,
          babelrc: false,
          presets: [
            [
              'env',
              {
                targets: {
                  browsers: ['last 2 versions', 'ie >= 10']
                },
                useBuiltIns: true
              }
            ],
            'react'
          ],
          plugins: getBabelPlugins()
        }
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            {
              loader: 'css',
              options: {
                importLoaders: 1,
                sourceMap: true,
                modules: CSSModules,
                // "context" and "localIdentName" need to be the same with server config,
                // or the style will flick when page first loaded
                context: path.join(process.cwd(), './src'),
                localIdentName: isDev ? '[name]__[local].[hash:base64:5]' : '[hash:base64:5]',
                minimize: !isDev
              }
            },
            {
              loader: 'postcss'
            }
          ]
        })
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader'
            }
          ]
        }),
        include: [/node_modules[/\\]animate.css/,
          /flexboxgrid/,
          /react-table/,
          /react-datepicker/,
          /react-checkbox/
        ]
      },
      {
        test: /\.(woff2?|ttf|eot|svg)$/,
        loader: 'url',
        options: { limit: inlineLimit }
      },
      {
        test: webpackIsomorphicToolsPlugin.regular_expression('images'),
        // Any image below or equal to 10K will be converted to inline base64 instead
        use: [
          {
            loader: 'url',
            options: { limit: inlineLimit }
          },
          // Using for image optimization
          {
            loader: 'image-webpack',
            options: { bypassOnDebug: true }
          }
        ]
      }
    ]
  },
  plugins: getPlugins(),
  // Where to resolve our loaders
  resolveLoader: {
    modules: ['src', 'node_modules'],
    moduleExtensions: ['-loader']
  },
  resolve: {
    modules: ['src', 'node_modules'],
    descriptionFiles: ['package.json'],
    moduleExtensions: ['-loader'],
    extensions: ['.js', '.jsx', '.json']
  },
  // Some libraries import Node modules but don't use them in the browser.
  // Tell Webpack to provide empty mocks for them so importing them works.
  // https://webpack.github.io/docs/configuration.html#node
  // https://github.com/webpack/node-libs-browser/tree/master/mock
  node: {
    fs: 'empty',
    vm: 'empty',
    net: 'empty',
    tls: 'empty'
  }
}
v2 app.js
// app.js

  const config = require('../tools/webpack/webpack.client.babel')

  app.use(require('koa-webpack')({
    config,
    dev: {
      publicPath: config.output.publicPath,
      noInfo: true,
      stats: 'minimal'
    },
    hot: { port: 3001 }  // this bit was added after 2.x migration as the default port 8081 is taken up in my PC
  }))

Expected Behavior

Hot reloading should work. Browser should show HMR connected in console.

Actual Behavior

Doesn't work. I neither see HMR connected message nor does the browser refreshes when I change source files. Webpack builds the changes.

How can we reproduce the behavior?

The same config (minus changes required for v2.x migration) worked without any issues with v1. Here are the relevant bits:

v1 webpack config
'use strict' // eslint-disable-line

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { CSSModules, inlineLimit } = require('./config')

const nodeEnv = process.env.NODE_ENV || 'development'
const isDev = nodeEnv !== 'production'

const WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin')
const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('./WIT.config')).development(isDev)

// Setting the plugins for development/production
const getPlugins = () => {
  // Common
  const plugins = [
    new ExtractTextPlugin({
      filename: '[name].[contenthash:8].css',
      allChunks: true,
      disable: isDev, // Disable css extracting on development
      ignoreOrder: CSSModules
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        // Javascript lint
        eslint: {},
        context: '/', // Required for the sourceMap of css/sass loader
        debug: isDev,
        minimize: !isDev
      }
    }),
    // Style lint
    new StyleLintPlugin({ files: ['src/**/*.css'], quiet: false }),
    // Setup environment variables for client
    new webpack.EnvironmentPlugin({ NODE_ENV: JSON.stringify(nodeEnv) }),
    // Setup global variables for client
    new webpack.DefinePlugin({
      __CLIENT__: true,
      __SERVER__: false,
      __DEV__: isDev
    }),
    new webpack.NoEmitOnErrorsPlugin(),
    webpackIsomorphicToolsPlugin,
    new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: module => /node_modules/.test(module.resource) })
  ]

  if (isDev) {
    // For development
    plugins.push(
      new webpack.HotModuleReplacementPlugin(),
      // Prints more readable module names in the browser console on HMR updates
      new webpack.NamedModulesPlugin(),
      new webpack.IgnorePlugin(/webpack-stats\.json$/),
      new BundleAnalyzerPlugin({
        analyzerMode: 'static',
        openAnalyzer: false
      })
    )
  } else {
    plugins.push(
      // For production
      new webpack.HashedModuleIdsPlugin(),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        beautify: false,
        mangle: { screw_ie8: true },
        compress: {
          screw_ie8: true, // React doesn't support IE8
          warnings: false,
          unused: true,
          dead_code: true
        },
        output: { screw_ie8: true, comments: false }
      })
    )
  }

  return plugins
}

// get babel plugins for dev/production
const getBabelPlugins = () => {
  const plugins = [
    'react-hot-loader/babel',
    'transform-object-rest-spread',
    'transform-class-properties',
    [
      'transform-imports',
      {
        'redux-form': {
          transform: 'redux-form/es/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        },
        lodash: {
          transform: 'lodash/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        }
      }
    ]
  ]

  if (isDev) {
    plugins.push('transform-react-jsx-source')
  }

  return plugins
}

// Setting the entry for development/production
const getEntry = () => {
  // For development
  let entry = [
    'babel-polyfill', // Support promise for IE browser (for dev)
    'react-hot-loader/patch',
    'webpack-hot-middleware/client?reload=true',
    './src/client.js'
  ]

  // For production
  if (!isDev) {
    entry = {
      main: './src/client.js'
    }
  }

  return entry
}

// Setting webpack config
module.exports = {
  name: 'client',
  target: 'web',
  cache: isDev,
  devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
  context: path.join(process.cwd()),
  entry: getEntry(),
  output: {
    path: path.join(process.cwd(), './build/public/assets'),
    publicPath: '/assets/',
    // Don't use chunkhash in development it will increase compilation time
    filename: isDev ? '[name].js' : '[name].[chunkhash:8].js',
    chunkFilename: isDev ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
    pathinfo: isDev
  },
  module: {
    noParse: [/dtrace-provider/, /safe-json-stringify/, /mv/, /source-map-support/],
    rules: [
      {
        test: /\.jsx?$/,
        enforce: 'pre',
        exclude: /node_modules/,
        loader: 'eslint',
        options: {
          fix: true
        }
      },
      {
        test: /node_modules[/\\]jsonstream/i,
        loader: 'shebang'
      },
      {
        test: /\.jsx?$/,
        loader: 'babel',
        exclude: /node_modules/,
        options: {
          cacheDirectory: isDev,
          babelrc: false,
          presets: [
            [
              'env',
              {
                targets: {
                  browsers: ['last 2 versions', 'ie >= 10']
                },
                useBuiltIns: true
              }
            ],
            'react'
          ],
          plugins: getBabelPlugins()
        }
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            {
              loader: 'css',
              options: {
                importLoaders: 1,
                sourceMap: true,
                modules: CSSModules,
                // "context" and "localIdentName" need to be the same with server config,
                // or the style will flick when page first loaded
                context: path.join(process.cwd(), './src'),
                localIdentName: isDev ? '[name]__[local].[hash:base64:5]' : '[hash:base64:5]',
                minimize: !isDev
              }
            },
            {
              loader: 'postcss'
            }
          ]
        })
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader'
            }
          ]
        }),
        include: [/node_modules[/\\]animate.css/,
          /flexboxgrid/,
          /react-table/,
          /react-datepicker/,
          /react-checkbox/
        ]
      },
      {
        test: /\.(woff2?|ttf|eot|svg)$/,
        loader: 'url',
        options: { limit: inlineLimit }
      },
      {
        test: webpackIsomorphicToolsPlugin.regular_expression('images'),
        // Any image below or equal to 10K will be converted to inline base64 instead
        use: [
          {
            loader: 'url',
            options: { limit: inlineLimit }
          },
          // Using for image optimization
          {
            loader: 'image-webpack',
            options: { bypassOnDebug: true }
          }
        ]
      }
    ]
  },
  plugins: getPlugins(),
  // Where to resolve our loaders
  resolveLoader: {
    modules: ['src', 'node_modules'],
    moduleExtensions: ['-loader']
  },
  resolve: {
    modules: ['src', 'node_modules'],
    descriptionFiles: ['package.json'],
    moduleExtensions: ['-loader'],
    extensions: ['.js', '.jsx', '.json']
  },
  // Some libraries import Node modules but don't use them in the browser.
  // Tell Webpack to provide empty mocks for them so importing them works.
  // https://webpack.github.io/docs/configuration.html#node
  // https://github.com/webpack/node-libs-browser/tree/master/mock
  node: {
    fs: 'empty',
    vm: 'empty',
    net: 'empty',
    tls: 'empty'
  }
}
v1 app.js
// app.js

  const config = require('../tools/webpack/webpack.client.babel')

  app.use(require('koa-webpack')({
    config,
    dev: {
      publicPath: config.output.publicPath,
      noInfo: true,
      stats: 'minimal'
    }
  }))

Non-Existent Assets Have No Response

As noticed by @christensson, assets (js, images, css, etc) which don't exist don't generate the correct server response. No response code is sent, and the response just hangs.

Let's say that I setup the webpack configuration to dynamically serve /js/bundle.js which is referenced from index.html which is statically served from another middleware. I found out that if I do a curl for localhost:/js/bundle2.js which webpack isn't setup to dynamically serve nothing happens, no response is returned, no 404, no nothing....

UNMET PEER DEPENDENCY [email protected]

I have this version installed though:

"devDependencies": {
"koa-webpack": "^0.1.9",
"nodemon": "^1.11.0",
"webpack": "2.1.0-beta.27"
},

I also have 2.1.0-beta.27 installed globally.

Also, is it a good idea to depend on a beta version of webpack? What's the reason behind it? Seems like this would make the build unstable. We just need a version of this that works and is reliable. Desperately.

The hook "failed" does not exist on a MultiCompiler

Thanks for the super helpful project!

  • Node Version: 9.6.1
  • koa Version: 2.5.0
  • koa-wepback Version: 3.0.1
  • webpack Version: 4.1.1

It appears that koa-webpack does not wait for the build to finish using Webpack 4 (probably due to new async rendering stuff). When a change is made, but before it has finished compiling, a request to the server ends with a 500 and the following in the logs:

  TypeError: Cannot read property 'tap' of undefined
      at Promise (/Users/mike/Code/boltline/app/node_modules/koa-webpack/index.js:24:29)
      at new Promise (<anonymous>)
      at waitMiddleware (/Users/mike/Code/boltline/app/node_modules/koa-webpack/index.js:19:12)
      at /Users/mike/Code/boltline/app/node_modules/koa-webpack/index.js:31:5
      at app.use (/Users/mike/Code/boltline/app/server.development.js:31:10)
      at dispatch (/Users/mike/Code/boltline/app/node_modules/koa-compose/index.js:42:32)
      at /Users/mike/Code/boltline/app/node_modules/koa-compose/index.js:34:12
      at Application.handleRequest (/Users/mike/Code/boltline/app/node_modules/koa/lib/application.js:150:12)
      at handleRequest (/Users/mike/Code/boltline/app/node_modules/koa/lib/application.js:132:19)
      at Server.proxy (/Users/mike/Code/boltline/app/server/addProxy.js:33:9)
      at Server.emit (events.js:127:13)
      at parserOnIncoming (_http_server.js:642:12)
      at HTTPParser.parserOnHeadersComplete (_http_common.js:117:17)

Once the build finishes, everything continues as expected. This began after upgrading to webpack 4.

// webpack.config.js
module.exports = [
  {
    // ...any valid config
  },
  {
    // ...any valid config
  }
];

Continuation error when using lazy mode

  • Node Version: v7.9.0
  • NPM Version: yarn v0.22.0
  • koa Version: v2.2.0
  • koa-wepback Version: v0.4.0

Example snippet:

app.use(async (ctx, next) => {
  console.log("Handing control to middleware");
  await next();
  console.log("Received control from middleware");
  console.log("Body is set?", !!ctx.body);
});
app.use(koaWebpack({
  compiler: webpack(webpackConfig),
  dev: {
    publicPath: '/',
    noInfo: true,
    // lazy: true is important
    lazy: true,
  },
}));

Expected Behavior

The koa-webpack middleware blocks on and handles requests for resources that webpack would handle.

Actual Behavior

Control is passed back to koa, and later the middleware tries to send a response even though the server has already sent a 404 (or potentially something else). Here is the console output of the above:

Handing control to middleware
webpack building...
Received control from middleware
Body is set? false
webpack built f7bc127c6bdda045c586 in 920ms
_http_outgoing.js:371
    throw new Error('Can\'t set headers after they are sent.');
    ^

Error: Can't set headers after they are sent.

How can we reproduce the behavior?

Using the snippet above. More specifically, the issue exists in this code:

return async (context, next) => {
  await waitMiddleware();
  await dev(context.req, {
    end: (content) => {
      context.body = content;
    },
    setHeader: context.set.bind(context),
    locals: context.state
  }, next);
};

The call to dev, which is the function provided by webpack-dev-middleware,
does not explicitly return anything, though it does, under some branches, call
return next(). Since the next we are passing above is a function that
returns a promise, this works some of the time. However, with lazy: true, it
will return undefined, and the await above will end synchronously, ending the
middleware and passing control back to koa, which will probably return a 404.
However, the webpack-dev-middleware may eventually compile the file and then
try to set the headers and body to send the response, even though koa has
already finished with it.

I would propose a solution like this:

return async (context, next) => {
  await waitMiddleware();
  await new Promise((resolve, reject) => {
    dev(context.req, {
      end: (content) => {
        context.body = content;
        resolve();
      },
      setHeader: context.set.bind(context),
      locals: context.state
    }, () => resolve(next()));
  });
};

I'm also not sure if this affects the hot middleware, though it seems to be
using a similar pattern of passing the next to the callback function. If this
fix looks acceptable, I am willing to open a pull request with the changes.

[v2.0.3] Doesn't seem to pick up the babel presets.

I bumped to latest koa-webpack version, did the necessary changes suggested in the update notes. But can't seem to succeed with the compilation step. Doesn't seem to pick up the babel config for react(jsx). Not sure what am i missing here, But I end up with the below error.

ERROR in ../src/index.js
Module parse failed: Unexpected token (27:2)
You may need an appropriate loader to handle this file type.
| 	const app = (
| 		<ReactHotLoader>
| 			<ReduxProvider store={store}>
@ multi react-hot-loader/patch regenerator-runtime/runtime ../src/index.js
โ„น ๏ฝขwdm๏ฝฃ: Failed to compile.

Is there a config change I'm missing out with changes around babel transpilation ? Will be happy to provide more information if needed. @shellscape

[Edit]
Works fine on the previous version. So I might be missing something here.

Passing in hot: false does not disable HMR

  • Node Version: v8.2.1
  • NPM Version: yarn v1.3.2
  • koa Version: v2.0.0-alpha.7
  • koa-wepback Version: ^2.0.3

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your
repository rather than pasting code. Otherwise, please paste relevant short snippets below.

// webpack.config.js
...
  devServer: {
    hot: false,
  },
...
// ./server/middleware/hotClient.js
const server = new Koa()
server.use(
  middleware({
    compiler,
    config: webpackConfig,
    dev: {
      logger: log,
      stats: 'minimal',
      publicPath,
      contentBase,
    },
    hot: {
      hot: false,
      // logLevel: 'silent',
    },
  })
)
server.listen(3000)

Expected Behavior

No websocket server should start.

Actual Behavior

Websocket server starts, and the client page tries to connect.

 NFO  Running [main]...
 CLI  Loading [development][main] environmental variables...
 NFO  Loaded environment variables are available in debug mode.
 NFO  Run yarn:run -i <webApp> to enable.
 CLI  Registering API with LocoProxy...
 CLI  Connected to DevOpz tunneler.
 CLI  Found host: MAIN_API_ROOT=https://xxx
 CLI  Registering CLIENT with LocoProxy...
 CLI  [nodemon] 1.14.11
 CLI  [nodemon] reading config ./nodemon.json
 CLI  [nodemon] to restart at any time, enter `rs`
 CLI  [nodemon] watching extensions: js,mjs,json
 CLI  [nodemon] starting `node -r babel-register -r babel-polyfill ./main/server/index.js`
 CLI  [nodemon] spawning
 CLI  [nodemon] child pid: 21760
 CLI  [nodemon] watching 396 files
 CLI  Connected to DevOpz tunneler.
 CLI  Found host: MAIN_API_ROOT=https://xxx
 CLI  Found host: MAIN_CLIENT_ROOT=https://xxx
 CLI  Found host: CLIENT_ROOT=https://xxx
 CLI  Starting webpack build...
โ„น ๏ฝขhot๏ฝฃ: webpack: Compiling...
โœ– ๏ฝขhot๏ฝฃ: WebSocket Server Error { Error: listen EADDRINUSE 127.0.0.1:8081
    at Object.exports._errnoException (util.js:1024:11)
    at exports._exceptionWithHostPort (util.js:1047:20)
    at Server.setupListenHandle [as _listen2] (net.js:1319:14)
    at listenInCluster (net.js:1367:12)
    at GetAddrInfoReqWrap.doListen (net.js:1493:7)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:97:10)
  code: 'EADDRINUSE',
  errno: 'EADDRINUSE',
  syscall: 'listen',
  address: '127.0.0.1',
  port: 8081 }
 CLI  Creating [main] server instance...
 CLI  Connected to MongoDB at mongodb://127.0.0.1/ethos
 CLI  [main] is ready and serving from port [8000].

The EADDRINUSE is irrelevant, of course, the server must still be running from a previously-killed process. However I would expect the server not to try to start at all.

How can we reproduce the behavior?

Koa errors generate Unhandled promise rejection warnings

  • Node Version: 7.9.0
  • NPM Version: 4.2.0
  • koa Version: 2.2.0
  • koa-wepback Version: 0.4.0

Issue

koa-webpack middleware generates UnhandledPromiseRejectionWarning warnings when errors are raised in Koa apps. This happens in even the most trivial of webpack/app setups.

Removing the koa-webpack middleware makes the issue go away.

Expected Behavior

Unhandled promise rejections should be handed so that no warnings should be generated.

Actual Behavior

(node:1642) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Can't set headers after they are sent.
(node:1642) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

How can we reproduce the behavior?

Attach the koa-webpack middleware and access an invalid (404) route to see the warning appear in the console.

hot reload don't work

When i run entry.js,it always throws new WebpackOptionsValidationError(webpackOptionsValidationErrors); ,it's about plugins, when i remove the plugins, it runs, but hot reload don't work. I also read the webpack-hot-middleware,but it needs plugins, i guess it's noting about plugins ๐Ÿ˜•
This is my webpack.config.js
`const path = require('path')
const webpack = require('webpack')

module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/app.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
},
module: {
rules: [{
test: /.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
'presets': ['es2015']
}
},
{
test: /.css$/,
loader: 'style!css?modules'
},
{
test: /.(png|jpg|gif|svg)$/,
loader: 'file',
options: {
name: 'assets/images/[name].[ext]?[hash]'
}
}
],
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
}entry.jsapp.use(devWebp({
dev: {
publicPath: config.output.path,
headers: { 'Content-Type': 'text/html; charset=utf-8' },
stats: { colors: true },
quiet: false,
noInfo: true
},
hot: {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}
}))` ๐Ÿ™

Unable to get server-side hot reloading working

Thanks for this project. I'm having trouble getting hot reloading to work, so I thought I would create a "hello world" complete project to demonstrate. https://github.com/cmoad/koa-webpack-hmr-test

You should be able to clone the above repo then npm install and npm start.

If I curl localhost:5000 I get ok. I then change ok to test in index.js. I can see webpack recompile on the command line, but if I curl localhost:5000 I still get ok.

I should also note that I can't get webpack to run without the plugin, new webpack.IgnorePlugin(/webpack/). Without that I see a lot of Module not found and Module parse failed from webpack dependencies.

Typo in README

The hotClient section still refers to the property name as hot in the paragraph.

e.g.

The hot property ...

(Sorry for not PR'ing this, short on time right now!)

An error occurred when i set hot true

The Issues page for this repository is not a support forum, it is for reporting potential bugs in this module, which
composes webpack-hot-middleware and webpack-dev-middle for use with koa2.
If you have arrived here because you cannot get webpack-hot-middleware
or webpack-dev-middleware working, please review the documentation
for the respective middleware you are experiencing a problem with. If you proceed with this form, please fill out all fields, or your issue may be closed as "invalid." Please remove this header to acknowledge this message.

  • Node Version:9.8.0
  • NPM Version:5.6.0
  • koa Version:2.5.0
  • koa-wepback Version:3.0.2
 {
    devtool: "source-map",
    module: {
        rules: [
            {
                test: /\.(js|jsx)?/,
                include: [
                    path.resolve(__dirname, '../src')
                ],
                exclude: [
                    path.resolve(__dirname, '../node_modules'), path.resolve(__dirname, '../src/index.html')
                ],
                loader: ['babel-loader', 'eslint-loader']
            },
            {
                test: /.(css|less)$/,
                use: ['style-loader', 'css-loader', {loader: 'less-loader', options: { javascriptEnabled: true }}]
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        name: 'static/img/[name][hash:7].[ext]'
                    }
                }]
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        name: 'static/fonts/[name][hash:7].[ext]'
                    }
                }]
            }
        ]
    },
    resolve: {
        extensions: [".js", ".json", ".jsx", ".css", ".less"]
    }
}

merge(baseWebpackConfig, {
    mode: 'development',
    entry: {
        app: ['webpack-hot-middleware/client?reload=true', path.resolve(__dirname, '../src/index')],
        vendor: ['react', 'react-dom', 'dva', 'lodash']
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/',
        filename: 'js/[name].js',
        chunkFilename: 'js/[name].js',
        sourceMapFilename: '[file].map'
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                default: false,
                commons: {
                    test: /react|react-dom|dva|lodash/,
                    name: "vendor",
                    chunks: "all"
                }
            }
        }
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HtmlWebpackPlugin({
            title: 'AWM',
            favicon: path.resolve(__dirname, '../src/assets/favicon.ico'),
            filename: 'index.html',
            template: path.resolve(__dirname, '../src/index.html'),
            chunks: ['app', 'vendor']
        })
    ]
})

error:
image

Non-Existent Resources Have No Response

As noticed in #4 ,pathsใ€assets which koa don't handle or don't exist ,don't generate the correct server response. No response code is sent, and the response just hangs.
github test repo is here.
the procedure is below:
1.koa2 entry js
image

2.webpack 2 config js
image

3.client entry js
image

4.effect
hangs

Tests

We're in dire need of tests and I'm short on time at the moment. Ideal setup would be with:

  • Mocha or Ava
  • PhantomJS or Electron
  • Vue.js or React
  • Koa2 (required)
  • Webpack (required)

application/octet-stream

Unless I set a header, it's forcing application/octet-stream, which causes my page to download.

app.use(async (ctx) => {
  ctx.res.setHeader('Content-Type', 'text/html');
  ctx.body = '...';
});

Can this be avoided?

Returning a promise when calling koa-webpack makes it awkward to work with.

  • Node Version: 9.6.1
  • NPM Version: 5.7.1
  • koa Version: 2.5.1
  • koa-wepback Version: 5.0.2

Expected Behavior

To use the koa-webpack middleware in the same way any other middleware is used.

Actual Behavior

Calling the new version of koa-webpack doesn't actually return a middleware, but it returns a promise instead, which needs to be awaited. It makes things a little bit awkward since now all the server logic which must come after this middleware needs to be put inside a .then of the promise, which can be quite a bit of code. Compounding this problem is the fact that the middleware initialization is usually done in a top-level scope where await can't be used (without wrapping it in a IIFE).

Support server hot reloading using webpack-hot-server-middleware

  • Node Version: n/a
  • NPM Version: n/a
  • koa Version: n/a
  • koa-wepback Version: n/a

Expected Behavior

For the server to properly hot reload without having to restart.

Actual Behavior

Not possible to integrate webpack-hot-server-middleware

How can we reproduce the behavior?

By attempting to setup webpack-hot-server-middleware.

The primary problem is that this package expects a single compiler but to properly support SSR it needs to support a MultiCompiler instance which contains both server and client compilers. The MultiCompiler instance can be passed to the dev middleware but the hot middleware only needs to receive the client.

There are two solutions here:

  1. Allow setting which compiler 'name' to use for the hot client middleware. The advantage here is that it leaves the implementation of the server middleware to the user.
  2. Do the implementation of the hot server middleware within the package. The advantage to this is that it follows the apparent spirit of this package where it attempts to manage all the dependencies and middleware setup for the user.

I would be happy to open a PR for this but would like feedback from @shellscape on the preferred approach. For now I have rolled my own integration with Koa but keeping up with updates is a pain considering that it is all nearly duplicated with this package. My only change is to support the use of a MultiCompiler.

This is a more fleshed out version of issue #66 which attempts to make a feature request fit the project issue template.

koa-webpack 5.* on egg framework of koa2 can not work

The Issues page for this repository is not a support forum, it is for reporting potential bugs in this module, which
composes webpack-hot-middleware and webpack-dev-middle for use with koa2.
If you have arrived here because you cannot get webpack-hot-middleware
or webpack-dev-middleware working, please review the documentation
for the respective middleware you are experiencing a problem with. If you proceed with this form, please fill out all fields, or your issue may be closed as "invalid." Please remove this header to acknowledge this message.

  • Node Version: 8.11.1
  • NPM Version: 5.6.0
  • koa Version: 2
  • koa-wepback Version: 5.0.2

Expected Behavior

Actual Behavior

My koa framwork is egg . I update koa-webpack 3.* to 5.0.2, koa-webpack can not work. but i can not find reason with debug ( koa-webpack 3.* is ok ).

wx20180616-194857 2x

And this is my egg config of koa-webpack 5.*:

wx20180616-194938 2x

On koa-webpack 3.* it ok.
wx20180616-195752 2x
wx20180616-195809 2x

How can we reproduce the behavior?

Get error when use fileSystem.readFileSync

  • Node Version:
    v7.7.3

  • NPM Version:
    4.5.0

  • koa Version:
    2.0.0

  • koa-wepback Version:
    0.3.1

// webpack.config.js
var path = require( "path" );
var webpack = require( 'webpack' );

module.exports = {
  entry: {
    app: [ "webpack-hot-middleware/client?reload=1", "./src/main.js" ]
  },
  output: {
    path: path.resolve( __dirname, 'dist' ),
    publicPath: "/assets/",
    filename: "bundle.js"
  },
  module: {
    loaders: [
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      }
    ]
  },
  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
  ]
};
// app.js
require( "babel-polyfill" );
var webpack = require( 'webpack' )
var koaWebpack = require('koa-webpack');
var webpackConf = require( './webpack.config' )
var Koa = require( 'koa' )
var app = new Koa()
var compiler = webpack( webpackConf );
var middleware = koaWebpack({
  compiler:compiler , 
  dev:{
  noInfo: false,
  publicPath: webpackConf.output.publicPath
} 
}) 
app.use( middleware  )
app.use( ctx => {
  console.log(middleware.dev.fileSystem);
  const htmlBuffer = middleware.dev.fileSystem.readFileSync(`./index.html`);
  ctx.type = 'html';
  ctx.body = htmlBuffer; 
} )
app.listen( 3000 );

Expected Behavior

just rebuild html files in stream but do not need press F5 when change index.html

Actual Behavior

get error

MemoryFileSystem { data: { home: { '': true, clyde: [Object] } } }

  Error
      at pathToArray (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/memory-fs/lib/MemoryFileSystem.js:44:10)
      at MemoryFileSystem.readFileSync (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/memory-fs/lib/MemoryFileSystem.js:103:13)
      at app.use.ctx (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/app.js:37:48)
      at dispatch (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/koa-compose/index.js:44:32)
      at next (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/koa-compose/index.js:45:18)
      at dispatch (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/koa-compose/index.js:44:32)
      at next (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/koa-compose/index.js:45:18)
      at middleware (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/webpack-hot-middleware/middleware.js:26:48)
      at _callee2$ (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/koa-webpack/dist/index.js:127:22)
      at tryCatch (/home/clyde/Desktop/temp/ygm125/webpack/demo/webpack-hot-middleare/node_modules/regenerator-runtime/runtime.js:64:40)

How can we reproduce the behavior?

git clone https://github.com/dxcqcv/koa-demo.git
then run node app.js in that folder

Memory leak with Webpack4

The Issues page for this repository is not a support forum, it is for reporting potential bugs in this module, which
composes webpack-hot-middleware and webpack-dev-middle for use with koa2.
If you have arrived here because you cannot get webpack-hot-middleware
or webpack-dev-middleware working, please review the documentation
for the respective middleware you are experiencing a problem with. If you proceed with this form, please fill out all fields, or your issue may be closed as "invalid." Please remove this header to acknowledge this message.

  • Node Version: tried 9 and 10
  • NPM Version: 6.2.0
  • Yarn Version: 1.3.2
  • koa Version: 2.3.0
  • koa-wepback Version: 5.1.0

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your
repository rather than pasting code. Otherwise, please paste relevant short snippets below.

// webpack.config.js
// app.js

Expected Behavior

HMR should work

Actual Behavior

when HMR was enabled when code changes, it starts compiling and then there is a memory leak that crashes the whole app

How can we reproduce the behavior?

It is very hard to replicate our whole configuration.

I can mention the plugins we use:
name-all-modules-plugin
circular-dependency-plugin
extract-css-chunks-webpack-plugin
NoEmitOnErrorsPlugin
stats-webpack-plugin
write-file-webpack-plugin

await ctx.render 404

await dev(context.req, {
      end: (content) => {
        context.body = content;
      },
      setHeader: context.set.bind(context),
      locals: context.state
    }, next);
shared.handleRequest(filename, processRequest, req);

webpack-dev-middleware is not return Promise, koa.use middleware, koa next await is broken.

Build of 0.5.0 does not contain recent changes

  • Node Version: v7.9.0
  • NPM Version: v4.2.0
  • koa-wepback Version: v0.5.0

To illustrate:

$ npm view [email protected] dist.tarball | xargs curl -s | tar -xzO package/dist/index.js | md5sum
d41d8cd98f00b204e9800998ecf8427e  -
$ npm view [email protected] dist.tarball | xargs curl -s | tar -xzO package/dist/index.js | md5sum
d41d8cd98f00b204e9800998ecf8427e  -

The dist/index.js file from the package tarball is the same in 0.5 as it was in 0.4. This means it's missing the changes from #49.

TypeError: webpack-hot-client: `entry` Object values must be an Array or Function.

I've got this error:

TypeError: webpack-hot-client: `entry` Object values must be an Array or Function. Please check your webpack config.
  • Node Version: v8.9.1
  • NPM Version: 5.5.1
  • koa Version: 2.5.2
  • koa-wepback Version: 5.1.0

My entry config is like:

entry: {
  home: 'src/pages/home/index.js',
  about: 'src/pages/about/index.js'
}

And I use koa-webpack like this:

KoaWebpack({
  compiler,
  hotClient: {
    allEntries: true
  }
}).then(...);

How should I resolve this?

`Content-Type:application/octet-stream` being set for subsequent middleware

Already mentioned in #15 (and leecade/koa-webpack-middleware#23), but I thought I'd open a new issue.

Content-Type:application/octet-stream is being set for any middleware hit after this one. Besides being generally incorrect if you're trying to respond with html/text/json, it causes the browser (Chrome at least) to prompt for a download. Working around it means manually setting ctx.type to something more appropriate, or else making sure the webpack middleware only gets called on a route where it won't be a problem.

This behaviour is a symptom of context.body being unconditionally set to a stream (the passthrough) in the hot middleware part here. As soon as context.body gets assigned, Koa sets the appropriate content type, which then remains even after later reassigning body to a string or whatever.

Side note: writeHead should be setting context.status, not context.state, it should look like this:

writeHead: (status, headers) => {
  context.status = status;
  context.set(headers);
}

But the method that has been used to hook-in seems a bit hacky and brittle in general to me. I'll see if I can find the time to put together a PR, just wanted to raise this issue while it's in my head.

Thanks for creating this repo by the way, the other one isn't maintained very well ๐Ÿ˜›

Didn't work with typescript 2.1

typescropt 2.1 has supported async function,
but this module can't work with typescript,
it yield some error:

module.js:474
    throw err;
    ^

Error: Cannot find module 'babel-runtime/core-js/object/assign'
    at Function.Module._resolveFilename (module.js:472:15)
    at Function.Module._load (module.js:420:25)
    at Module.require (module.js:500:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/donghuashen/work/gitversion/OA/node_modules/koa-webpack/dist/index.js:7:15)
    at Module._compile (module.js:573:32)
    at Object.Module._extensions..js (module.js:582:10)
    at Module.load (module.js:490:32)
    at tryModuleLoad (module.js:449:12)
    at Function.Module._load (module.js:441:3)

Error: Cannot find module 'babel-runtime/core-js/object/assign'

  • Node Version: 9.3.0
  • NPM Version: 5.6.0
  • koa Version: 2.4.1
  • koa-wepback Version: 1.0.0

Expected Behavior

Works well without babel, I'm using typescript, so babel is unnecessary

Actual Behavior

Throw error unless I install babel-runtime manually

How can we reproduce the behavior?

https://github.com/JounQin/graphql-study

remove babel-runtime dependency, then yarn dev.

add babel-runtime as koa-webpack dependency should fix this, or find another way.

Missing babel-runtime

NPM: 4.6.1
Yarn: 0.21.3
Node: 7.10.0
Koa: 2.2.0
Koa-Webpack: 0.5.1

module.js:472
    throw err;
    ^

Error: Cannot find module 'babel-runtime/core-js/object/assign'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (C:\Users\jerom\Documents\GitHub\koa-angular\node_modules\koa-webpack\dist\index.js:7:15)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (C:\Users\jerom\Documents\GitHub\koa-angular\index.js:14:17)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)

Solved this issue with npm install babel-runtime --save-dev / yarn add babel-runtime -D.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.