Docker + Webpack(开发服务器)+ Yarnpkg不完整构建

时间:2018-03-08 19:11:08

标签: node.js docker webpack webpack-dev-server yarnpkg

问题

将当前在本地运行的webpack项目转换为在docker个容器内运行。此工作分为两个git分支:developcontainers

本地(无容器)

develop是稳定的基础,通过本地运行 在$ yarn install && npm run dev

中给出以下内容package.json
"scripts": {
    "start": "node .",
    "env:dev": "cross-env NODE_ENV=development",
    "env:prod": "cross-env NODE_ENV=production",
    "predev": "npm run prebuild",
    "dev": "npm run env:dev -- webpack-dev-server",
//[...]
}

分支develop确实包含yarn.lock,虽然FWIW,$ rm yarn.lock && yarn install --force && npm run dev确实正确启动了服务器,即GET http://localhost:3000为我提供了主页,因为我希望看到它。以上所有内容在$ git checkout containers

之后都一样

泊坞

关闭本地开发服务器后,我运行$ git checkout containers,此分支不包含yarn.lockpackage.lock。然后我运行$ docker-compose up --build web(在一个单独的终端中,在docker-compose.yaml中包含以下内容的兄弟目录中)

   web:
      build:
       context: ../frontend/
       dockerfile: Dockerfile
      env_file: ../frontend/.env
      volumes:
        - ../frontend/src:/code/src
      ports:
        - "3001:3000"
      depends_on:
        - api
      networks:
        - backend

服务frontend/Dockerfile的{​​{1}}就是这样

web

给出

# Dockerfile

FROM node:latest
RUN mkdir /code
ADD . /code/
WORKDIR /code/
RUN yarn cache clean && yarn install --non-interactive --force && npm rebuild node-sass

CMD npm run dev --verbose

所有似乎顺利,启动的最后一行是#frontend/.dockerignore node_modules deploy .circleci stories .storybook 然而,当我web_1 | Server is running at http://localhost:3000/.(注意GET http://localhost:3001中的端口映射)时,返回的页面不包含docker-compose中应该注入的预期<style>...</style>标记(如鉴于以下配置,<head> {我知道}

webpack

有趣的是,将此行添加到// https://github.com/diegohaz/arc/wiki/Webpack const path = require('path') const devServer = require('@webpack-blocks/dev-server2') const splitVendor = require('webpack-blocks-split-vendor') const happypack = require('webpack-blocks-happypack') const serverSourceMap = require('webpack-blocks-server-source-map') const nodeExternals = require('webpack-node-externals') const AssetsByTypePlugin = require('webpack-assets-by-type-plugin') const ChildConfigPlugin = require('webpack-child-config-plugin') const SpawnPlugin = require('webpack-spawn-plugin') const ExtractTextPlugin = require('extract-text-webpack-plugin') const { addPlugins, createConfig, entryPoint, env, setOutput, sourceMaps, defineConstants, webpack, group, } = require('@webpack-blocks/webpack2') const host = process.env.HOST || 'localhost' const port = (+process.env.PORT + 1) || 3001 const sourceDir = process.env.SOURCE || 'src' const publicPath = `/${process.env.PUBLIC_PATH || ''}/`.replace('//', '/') const sourcePath = path.join(process.cwd(), sourceDir) const outputPath = path.join(process.cwd(), 'dist/public') const assetsPath = path.join(process.cwd(), 'dist/assets.json') const clientEntryPath = path.join(sourcePath, 'client.js') const serverEntryPath = path.join(sourcePath, 'server.js') const devDomain = `http://${host}:${port}/` //[...] const sass = () => () => ({ module: { rules: [ { test: /\.(scss|sass)$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'sass-loader'}, ], }, ], }, }) const extractSass = new ExtractTextPlugin({ filename: 'style.css', }) const prodSass = () => () => ({ module: { rules: [ { test: /\.(scss|sass)$/, use: extractSass.extract({ use: [ { loader: 'css-loader', options: { minimize: true } }, { loader: 'sass-loader' }, ], fallback: 'style-loader', }), }, ], }, }) const babel = () => () => ({ module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader' }, ], }, }) const assets = () => () => ({ module: { rules: [ { test: /\.(png|jpe?g|svg|woff2?|ttf|eot)$/, loader: 'url-loader?limit=8000' }, ], }, }) const resolveModules = modules => () => ({ resolve: { modules: [].concat(modules, ['node_modules']), }, }) const base = () => group([ setOutput({ filename: '[name].js', path: outputPath, publicPath, }), defineConstants({ 'process.env.NODE_ENV': process.env.NODE_ENV, 'process.env.PUBLIC_PATH': publicPath.replace(/\/$/, ''), }), addPlugins([ new webpack.ProgressPlugin(), extractSass, ]), apiInsert(), happypack([ babel(), ]), assets(), resolveModules(sourceDir), env('development', [ setOutput({ publicPath: devDomain, }), sass(), ]), env('production', [ prodSass(), ]), ]) const server = createConfig([ base(), entryPoint({ server: serverEntryPath }), setOutput({ filename: '../[name].js', libraryTarget: 'commonjs2', }), addPlugins([ new webpack.BannerPlugin({ banner: 'global.assets = require("./assets.json");', raw: true, }), ]), () => ({ target: 'node', externals: [nodeExternals()], stats: 'errors-only', }), env('development', [ serverSourceMap(), addPlugins([ new SpawnPlugin('npm', ['start']), ]), () => ({ watch: true, }), ]), ]) const client = createConfig([ base(), entryPoint({ client: clientEntryPath }), addPlugins([ new AssetsByTypePlugin({ path: assetsPath }), new ChildConfigPlugin(server), ]), env('development', [ devServer({ contentBase: 'public', stats: 'errors-only', historyApiFallback: { index: publicPath }, headers: { 'Access-Control-Allow-Origin': '*' }, host, port, }), sourceMaps(), addPlugins([ new webpack.NamedModulesPlugin(), ]), ]), env('production', [ splitVendor(), addPlugins([ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }), ]), ]), ]) module.exports = client

package.json

并将Dockerfile的最后一行更改为 "dev-docker": "npm run predev && npm run env:dev -- webpack --progress --watch --watch-poll", 确实产生了预期的效果......

假设

我目前的怀疑是我遗漏了一些关于webpack开发服务器处理其加载器输出的方法,并且没有正确映射某个端口,但这是一个黑暗的镜头。

或者,CMD npm run dev-docker版本是个问题。本地是webpack-dev-server,其中docker's显示4.4.2,但这似乎不是问题,因为最新的文档符合我自己的设置。我已经确认加载器模块的5.6.0规范是每个规范的最新稳定版。

纵容

认识到这是一个由配置依赖和必然特殊方式的技术交叉引起的问题,我谦卑地请求你帮助解决这个依赖地狱。如果看起来我不明白一个特定的拼图如何运作,我很高兴听到它。任何想法,线索或建议,无论多么脆弱,都将受到极大的赞赏和利用,尽我所能。

3 个答案:

答案 0 :(得分:5)

在这里做远景,但是我试图在docker容器中运行grails-vue应用程序,并且遇到了webpack-dev-server的端口映射没有被正确暴露的问题。

我在github https://github.com/webpack/webpack-dev-server/issues/547上发现了这个问题,这导致我在package.json中将--host 0.0.0.0添加到我的dev任务中,如下所示:

"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0"

这解决了我的问题,也许这会帮助你找到答案。

答案 1 :(得分:2)

已经有一段时间了,但是回到这个问题,我找到了实际的答案。

webpack-dev-server使用两个端口。因此,仅公开一个端口(3000)时,我没有得到构建的文件,这些文件在client.js上的localhost:3001中提供。 JS控制台一直都在提供线索:GET localhost:3001/client.js上的连接被拒绝错误。

解决方案是公开容器上的两个端口,即 docker run -it -p 3000:3000 -p 3001:3001 --rm --entrypoint "npm run env:dev -- webpack-dev-server" ${CONTAINER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}

答案 2 :(得分:1)

本地安装的软件包可能与docker容器中的软件包不同。

为确保您安装了相同的软件包,您应该包含yarn.lockpackage.lock个文件。如果你只使用纱线yarn.lock就足够了。即使这不能解决您的具体问题,也可以防止其他问题,因为现在您已经确定了构建。