1

我需要部署一个 Web 应用程序,内置与打字稿反应。deploy 方法是构建运行 nginx 服务器的 docker 镜像,该服务器为静态构建提供服务,并将其放在 kubernetes 容器中。

构建脚本craco build在本地终端 (macOS) 中运行时可以正常工作。问题是在 docker 映像中运行相同的脚本时,它会返回错误:

Creating an optimized production build...
Failed to compile.

./src/views/main/routeConfigs.ts
Syntax error: Unexpected token : (7:25)

routeConfig.ts 文件的标题是

import { vueCompsInReact } from '@console/legacy-v1/vueDMZ';
import { IRoute } from 'models/router.models';
import { wrapReactifiedVueComponent } from 'views/common/routing/wrapReactifiedVueComponent';
import { ROUTE_KEY } from '../routes';
import Home from './Home';

export const MAIN_ROUTES: IRoute<ROUTE_KEY>[] = [{
    routeKey: ROUTE_KEY.R_HOME,
    path: '/',
    exact: true,
    component: Home,
}, 
...

并且Unexpected token : (7:25)是该行中的冒号“:”export const MAIN_ROUTES: IRoute<ROUTE_KEY>[]

我不明白的是它只在 docker 中失败。Dockerfile 是:

FROM node:12-alpine as builder

# define PROJECT_PATH to project 
ENV PROJECT_PATH=packages/console-core
ENV V1_PATH=legacy-v1
ENV APP_ROOT=/console-v2

RUN node -v
RUN mkdir ${APP_ROOT}
WORKDIR ${APP_ROOT}
# copy root package to install dependencies
COPY .nvmrc .stylelintrc.js package.json package-lock.json lerna.json ./
# copy console core package
RUN mkdir ./packages
RUN mkdir ./${PROJECT_PATH}
COPY ${PROJECT_PATH}/package.json ${PROJECT_PATH}/package-lock.json ${PROJECT_PATH}/craco.config.js ./${PROJECT_PATH}/
# copy console v1 package
RUN mkdir ./${V1_PATH}
COPY ${V1_PATH}/package.json ${V1_PATH}/package-lock.json ./${V1_PATH}/
# install dependencies
RUN npm install 
RUN npx lerna bootstrap 

COPY ${V1_PATH} ./${V1_PATH}
COPY ${PROJECT_PATH} ./${PROJECT_PATH}

# RUN cd ${PROJECT_PATH}
WORKDIR ${PROJECT_PATH}

RUN npm run build

使用命令RUN node -v我可以看到该node:12-alpine图像带有节点 12.18.3 版本,而在本地我有 12.14.0

package.json 文件是

{
  "name": "@console/core",
  "version": "2.0.0",
  "private": true,
  "description": "Core package of the web console",
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "serve": "serve -s build",
    "test": "npm run lint && craco test --transformIgnorePatterns \"node_modules/(?!(@snipsonian))\"",
    "eslint": "eslint --ext .js,.ts,.tsx src",
    "stylelint": "stylelint src/**/*.scss",
    "lint": "npm run eslint"
  },
  "dependencies": {
    "@console/legacy-v1": "^0.1.0",
    "@material-ui/core": "^4.11.0",
    "@material-ui/icons": "^4.9.1",
    "@snipsonian/browser": "^1.12.0",
    "@snipsonian/core": "^1.11.0",
    "@snipsonian/dvlp": "^1.12.0",
    "@snipsonian/observable-state": "^1.12.0",
    "@snipsonian/react": "^1.12.0",
    "@snipsonian/react-observable-state": "^1.12.0",
    "clsx": "^1.1.1",
    "flat": "^5.0.0",
    "gsap": "^3.5.1",
    "history": "^5.0.0",
    "immer": "^7.0.1",
    "oidc-client": "^1.10.1",
    "ramda": "^0.27.0",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router-dom": "^5.2.0",
    "reselect": "^4.0.0"
  },
  "devDependencies": {
    "@craco/craco": "^5.6.4",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "@types/flat": "^5.0.1",
    "@types/history": "^4.7.6",
    "@types/jest": "^24.9.1",
    "@types/node": "^12.12.47",
    "@types/ramda": "^0.27.7",
    "@types/react": "^16.9.36",
    "@types/react-dom": "^16.9.8",
    "@types/react-router-dom": "^5.1.5",
    "copy-webpack-plugin": "^6.0.3",
    "eslint": "^6.8.0",
    "http-proxy-middleware": "^1.0.4",
    "node-sass": "^4.14.1",
    "react-scripts": "3.4.1",
    "serve": "^11.3.2",
    "stylelint": "^13.6.0",
    "vue-loader": "^15.9.3",
    "vue-template-compiler": "^2.6.11",
    "winston": "^3.3.3",
    "yaml-loader": "^0.6.0"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all",
      "last 2 chrome version",
      "last 2 firefox version",
      "last 2 safari version",
      "not ie <= 11"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

craco.config.js 文件是:

/* eslint-disable @typescript-eslint/no-var-requires */
const { ESLINT_MODES, addBeforeLoader, loaderByName, getLoader } = require('@craco/craco');
const path = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies
const StyleLintPlugin = require('stylelint-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const CopyPlugin = require('copy-webpack-plugin');

const appSrc = path.resolve(__dirname, 'src');
const imagesConsoleV1 = path.resolve(__dirname, '../../legacy-v1/public/img');

module.exports = {
    eslint: {
        mode: ESLINT_MODES.file,
    },
    webpack: {
        alias: {
            /**
             * Add the aliases for all the top-level folders in the `src/` folder.
             * In combination with tsconfig.pathsOverride.json
             * See https://resir014.xyz/posts/2019/03/13/using-typescript-absolute-paths-in-cra-20/
             */
            api: `${appSrc}/api/`,
            config: `${appSrc}/config/`,
            models: `${appSrc}/models/`,
            state: `${appSrc}/state/`,
            utils: `${appSrc}/utils/`,
            views: `${appSrc}/views/`,
        },
        plugins: [
            new VueLoaderPlugin(),
            new StyleLintPlugin({
                configBasedir: __dirname,
                context: appSrc,
                files: ['**/*.scss'],
            }),
            new CopyPlugin({
                patterns: [
                    {
                        from: imagesConsoleV1,
                        transformPath(targetPath) {
                            return `img/${targetPath}`;
                        },
                    },
                ],
            }),
        ],
        configure: (webpackConfig /* , { env, paths } */) => {
            // console.log('webpackConfig', JSON.stringify(webpackConfig));

            /**
             * Loader-execution-order is from bottom to top!
             * And from right to left!
             */

            /* making sure the file-loader does not handle the .vue files */
            const getFileLoaderResult = getLoader(
                webpackConfig,
                loaderByName('file-loader'),
            );
            if (getFileLoaderResult.isFound) {
                const { match } = getFileLoaderResult;
                // console.log('file-loader found', match.loader);
                // console.log(match.loader.exclude);

                /* orig value: exclude: [ /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/ ], */
                match.loader.exclude = [ /\.(js|mjs|jsx|ts|tsx|vue)$/, /\.html$/, /\.json$/ ];
            }

            /* the yaml loader has to be placed 'before' (above) the file-loader
             * so that the yaml-loader is used on .yaml files instead of the file-loader (oneOf) */
            const yamlLoader = {
                test: /\.ya?ml$/,
                type: 'json', // Required by Webpack v4
                use: 'yaml-loader',
            };

            addBeforeLoader(webpackConfig, loaderByName('file-loader'), yamlLoader);

            /* adding the vue-loader
             * p.s. Doing it myself instead of "addBeforeLoader(webpackConfig, loaderByName('babel-loader'), vueLoader)"
             * because that adds the vueLoader inside te oneOf array instead of on the top-level.
             * Also "addAfterLoader" did not produce the expected behaviour. */
            // webpackConfig.resolve.alias['vue$'] = 'vue/dist/vue.esm.js';
            const vueLoader = {
                test: /\.vue$/,
                loader: 'vue-loader',
            };
            webpackConfig.module.rules.splice(0, 0, vueLoader); // adding it as the first element

            // console.log('webpackConfig.module', JSON.stringify(webpackConfig.module));

            return webpackConfig;
        },
    },
    jest: {
        configure: {
            moduleNameMapper: {
                /**
                 * Jest module mapper which will detect our absolute imports.
                 * In combination with tsconfig.pathsOverride.json
                 * See https://resir014.xyz/posts/2019/03/13/using-typescript-absolute-paths-in-cra-20/
                 */
                '^api(.*)$': '<rootDir>/src/api$1',
                '^config(.*)$': '<rootDir>/src/config$1',
                '^models(.*)$': '<rootDir>/src/models$1',
                '^state(.*)$': '<rootDir>/src/state$1',
                '^utils(.*)$': '<rootDir>/src/utils$1',
                '^views(.*)$': '<rootDir>/src/views$1',
                /**
                 * For the jest unit tests, we replace the vueDMZ (which serves as an entrypoint to the legacy v1 code)
                 * with a mock version, because otherwise jest has problems with the library imports in the legacy code
                 * (and problems with the vue code).
                 */
                '@console/legacy-v1/vueDMZ': '<rootDir>/../../legacy-v1/vueDMZ.jestMock',
            },
        },
    },
    babel: {
        plugins: [
            "@babel/plugin-proposal-optional-chaining",
        ],
    },
};

我不是网络应用程序专家,我的问题是 docker 映像中可能缺少哪些设置或本地启用的功能,这是造成此错误的原因,我理解为“无法解析最新的打字稿语法”

4

0 回答 0