在 docker 应用程序中启用 webpack 热重载

Posted

技术标签:

【中文标题】在 docker 应用程序中启用 webpack 热重载【英文标题】:Enabling webpack hot-reload in a docker application 【发布时间】:2017-07-15 16:16:17 【问题描述】:

我有一个带有以下容器的 docker 应用

    node - 项目的源代码。它提供位于公共文件夹中的 html 页面。 webpack - 监视节点容器中的文件,并在代码发生更改时更新公用文件夹(来自节点容器)。 数据库

这是 webpack/node 容器设置

 web:
    container_name: web
    build: .
    env_file: .env
    volumes:
      - .:/usr/src/app
      - node_modules:/usr/src/app/node_modules
    command: npm start
    environment:
      - NODE_ENV=development
    ports:
      - "8000:8000"

  webpack:
    container_name: webpack
    build: ./webpack/
    depends_on:
      - web
    volumes_from:
      - web
    working_dir: /usr/src/app
    command: webpack --watch

所以目前,webpack 容器监控和更新公共文件夹。我必须手动刷新浏览器才能看到我的更改。

我现在正在尝试合并 webpack-dev-server 以在浏览器中启用自动刷新

这些是我对 webpack 配置文件的更改

module.exports = 
  entry:[
    'webpack/hot/dev-server',
    'webpack-dev-server/client?http://localhost:8080',
    './client/index.js'
  ],

  ....

  devServer:
    hot: true,
    proxy: 
      '*': 'http://localhost:8000'
    
  

和新的 docker-compose 文件文件 webpack

  webpack:
    container_name: webpack
    build: ./webpack/
    depends_on:
      - web
    volumes_from:
      - web
    working_dir: /usr/src/app
    command: webpack-dev-server --hot --inline
    ports:
      - "8080:8080"

我在运行应用程序时似乎遇到了错误

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
webpack     |  - configuration.entry should be one of these:
webpack     |    object  <key>: non-empty string | [non-empty string]  | non-empty string | [non-empty string] | function
webpack     |    The entry point(s) of the compilation.
webpack     |    Details:
webpack     |     * configuration.entry should be an object.
webpack     |     * configuration.entry should be a string.
webpack     |     * configuration.entry should NOT have duplicate items (items ## 1 and 2 are identical) (
webpack     |         "keyword": "uniqueItems",
webpack     |         "dataPath": ".entry",
webpack     |         "schemaPath": "#/definitions/common.nonEmptyArrayOfUniqueStringValues/uniqueItems",
webpack     |         "params": 
webpack     |           "i": 2,
webpack     |           "j": 1
webpack     |         ,
webpack     |         "message": "should NOT have duplicate items (items ## 1 and 2 are identical)",
webpack     |         "schema": true,
webpack     |         "parentSchema": 
webpack     |           "items": 
webpack     |             "minLength": 1,
webpack     |             "type": "string"
webpack     |           ,
webpack     |           "minItems": 1,
webpack     |           "type": "array",
webpack     |           "uniqueItems": true
webpack     |         ,
webpack     |         "data": [
webpack     |           "/usr/src/app/node_modules/webpack-dev-server/client/index.js?http://localhost:8080",
webpack     |           "webpack/hot/dev-server",
webpack     |           "webpack/hot/dev-server",
webpack     |           "webpack-dev-server/client?http://localhost:8080",
webpack     |           "./client/index.js"
webpack     |         ]
webpack     |       ).
webpack     |       [non-empty string]
webpack     |     * configuration.entry should be an instance of function
webpack     |       function returning an entry object or a promise..

如您所见,我的条目对象没有任何重复项。

还有什么我应该做的吗?我错过了什么?

webpack-dev-server 基本上应该将所有请求代理到节点服务器。

【问题讨论】:

为什么要添加这些条目:'webpack/hot/dev-server'、'webpack-dev-server/client?localhost:8080'? @AdamWolski - 我相信这些路由允许浏览器建立到 webpack 服务器的套接字连接以启用自动更新 imo 您对“输入”字段及其含义有一些误解 @AdamWolski - 我哪里出错了? 【参考方案1】:

我遇到了同样的问题。这更多是我的错,而不是 webpack 或 docker。实际上,您必须检查 Dockerfile 中的 workdir 是否是 docker-compose.yml 中 bindmount 的目标

Dockerfile

FROM node
...
workdir /myapp
...

在你的 docker-compose.yml 上

web:
   ....
   -volumes:
        ./:/myapp

如果您在 webpack.config.js 上配置重新加载,它应该可以工作

【讨论】:

【参考方案2】:

Docker 和 webpack-dev-server 可以在没有任何中间件或插件的情况下完全运行,正确的配置是交易:

devServer: 
  port: 80, // use any port suitable for your configuration
  host: '0.0.0.0', // to accept connections from outside container
  watchOptions: 
      aggregateTimeout: 500, // delay before reloading
      poll: 1000 // enable polling since fsevents are not supported in docker
  

仅当您的 docker 容器不支持 fsevents 时才使用此配置。

为了提高性能,请查看 HosseinAgha 答案 #42445288:Enabling webpack hot-reload in a docker application

【讨论】:

【参考方案3】:

就我而言,我有一个 VueJS 应用程序。我按照Enabling Hot-Reloading with vuejs and vue-cli in Docker 帖子中的教程进行操作。我的解决方案是使用以下命令修改我的 dockerfile:

 FROM node:lts-alpine
 ...
 RUN yarn global add @vue/cli
 ...

它允许容器检测到我的代码中的更改并在我的浏览器中重新加载。就我而言,没有必要使用 devServer 创建 vue.config.js。

【讨论】:

【参考方案4】:

即使将我的项目文件夹安装到容器中,我也无法让 webpack 或 webpack-dev-server watch (--watch) 模式工作。 要解决此问题,您需要了解 webpack 如何检测目录中的文件更改。 它使用添加操作系统级别支持以监视文件更改的两个软件之一,称为inotifyfsevent。标准 Docker 镜像通常没有预装这些(特别是 linux 的 inotify),因此您必须将其安装在 Dockerfile 中。 在发行版的包管理器中查找 inotify-tools 包并安装它。幸运的是所有alpinedebiancentos 都有这个。

【讨论】:

这只是关于文件更改,这完全没有问题。 webpack 正在立即重新编译。实际问题是浏览器的热重载。浏览器不会自动刷新。这就是所谓的热重载(见问题标题) 其他答案启用 webpack 轮询,当文件系统树的深度增加时,这种轮询效率低下且呈指数级增长。通过安装 inotify,我们让 watchpack 监听更改事件而不是轮询。无需对这种情况启用轮询。 但问题不在于轮询。轮询和重新编译工作正常。这是关于浏览器没有重新加载。浏览器中有一个 sockjs 服务的东西调用了错误的 url,可能是这个原因,但我不知道。【参考方案5】:

尝试这样做:

    在 webpack 配置中添加 watchOptions.poll = true。

    手表选项: 民意调查:真 ,

    在 devServer config 中配置主机

    主机:“0.0.0.0”,

【讨论】:

我添加了配置,浏览器现在会自动更新 .. 但是更改并没有得到反映 :((即使在手动刷新之后) - 你会碰巧知道错误可能在哪里吗?控制台表明 webpack 确实更新了静态文件。 决定使用 webpack-dev-middleware 而不是只为 webpack 单独使用一个单独的 docker 容器。

以上是关于在 docker 应用程序中启用 webpack 热重载的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Webpack 4 中启用 SASS 模块

在 Docker 容器中调试 webpack-dev-server 应用程序

启用单页应用响应热重载 webpack

如何从 docker 容器运行 webpack 构建?

Webpack 4:有条件地启用 PostCSS 插件

如何设置“内容编码”以启用 Webpack 服务器的 gzip 文件