首页 > 解决方案 > 为什么我的 webpack 包在主机上成功构建但不在 docker 容器中?

问题描述

我的项目有一个这样的monorepo结构:

babel.config.js
  a-something
  b-something

我的项目根目录中有 babel 配置文件,并且包a-somethingb-something. 在包里面a-something我有以下 webpack 配置:

const path = require('path')

module.exports = {
  target: 'node',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'build')
  },
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.js?$/,
        use: {
          loader: 'babel-loader',
          options: {
            rootMode: 'upward'
          }
        },
        include: [
          path.resolve(__dirname, 'src'),
          /node_modules\/a-/,
          /node_modules\/b-/
        ]
      }
    ]
  }
}

在包里面a-something我有以下package.json:

{
  "name": "a-something",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "prod:build": "webpack --config webpack.config.js",
    "prod:start": "node build/bundle.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.2",
    "graphql": "^14.5.8",
    "graphql-request": "^1.8.2",
    "graphql-tag": "^2.10.1",
    "b-something": "^1.0.0",
    "node-fetch": "^2.6.0",
    "sitemap": "^5.0.0"
  },
  "devDependencies": {
    "webpack": "3.5.6",
    "@babel/polyfill": "7.7.0"
  }
}

我的根 package.json 具有以下依赖项:

"@babel/cli": "^7.5.5",
"@babel/core": "^7.5.5",
"babel-loader": "8.0.6"

最后我的 Dockerfile 里面的包a-something是:

FROM node:10.15.1
COPY ./package.json /src/package.json
ENV PORT 3000
ENV NODE_ENV production
WORKDIR /src
RUN npm install
COPY ./lerna.json /src/lerna.json
COPY ./packages/a-something/package.json /src/packages/a-something/package.json
COPY ./packages/b-something/package.json /src/packages/b-something/package.json
RUN npm run clean
COPY . /src
WORKDIR /src/packages/a-something
RUN npm run prod:build
RUN echo "FINISHED BUILDING!" 
EXPOSE ${PORT}
CMD ["npm" , "run", "prod:start"]

当我运行npm run prod: buildnpm run prod: start成功构建捆绑包时,但是当我构建 docker(其中上下文是根文件夹)时,我收到以下 npm 错误:

ERROR in Entry module not found: Error: Can't resolve 'babel-loader' in '/src/packages/a-something'
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! a-something@1.0.0 prod:build: `webpack --config webpack.config.js`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the a-something@1.0.0 prod:build script.

我的主机操作系统是 macOS Mojave。也许 Lerna 生成的符号链接在 Debian 上的处理方式不同(由 node image使用)?


更新:通过将所有与 babel 相关的 npm 包从根 package.jsondevDependencies的部分移动,问题得到解决。dependencies有谁知道为什么这会解决问题?

标签: javascriptdockerwebpackbabeljsbabel-loader

解决方案


正如我在问题的更新部分中提到的,解决方案是将所有与 babel 相关的包移动到devDependencies根 package.json 的部分。

但为什么这有帮助?

问题是我NODE_ENV在 Dockerfile 中设置为生产。如果设置为生产,npm将不会安装开发依赖项。NODE_ENV在主机上我没有这样的变量。此外@babel/polyfill,根据 babel docs ,另一个问题是:

因为这是一个 polyfill(它将在您的源代码之前运行),我们需要它是一个依赖项,而不是一个 devDependency

根据文档 @babel/polyfill也已弃用,因此更好的解决方案是:

  1. 添加"babel-loader": "8.0.6"到根 package.json
  2. devDependenciesa-somethingpackage.json中有以下内容:
    "devDependencies": {
        "webpack": "3.5.6",
        "core-js": "^3.4.7",
        "regenerator-runtime": "^0.13.3"
      }
  1. 将这两行放在最顶部的条目 Javascript 文件中:
import 'core-js/stable'
import 'regenerator-runtime/runtime'
  1. 最后使用这个 webpack 配置:
    const path = require('path')

    module.exports = {
      target: 'node',
      entry: './src/index.js',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'build')
      },
      module: {
        rules: [
          {
            test: /\.js?$/,
            use: {
              loader: 'babel-loader',
              options: {
                rootMode: 'upward',
                presets: [
                  ['@babel/preset-env', {
                    corejs: 3,
                    useBuiltIns: 'usage'
                  }]
                ]
              }
            },
            include: [
              path.resolve(__dirname, 'src'),
                /node_modules\/a-/,
                /node_modules\/b-/
            ]
          }
        ]
      }
    }

推荐阅读