SyntaxError: Неожиданный токен '<' при докеризации приложения реакции - PullRequest
1 голос
/ 16 февраля 2020

У меня есть реактивный проект с Webpack, который я пытаюсь докеризировать, следуя этой статье .

Dockerfile:

FROM node:12.14.1

RUN npm install webpack -g

WORKDIR /tmp
COPY package.json /tmp/
RUN npm config set registry http://registry.npmjs.org/ && npm install

WORKDIR /usr/app
COPY . /usr/app/
RUN cp -a /tmp/node_modules /usr/app/

RUN webpack

ENV NODE_ENV=production
ENV PORT=4000

CMD [ "/usr/local/bin/node", "--experimental-modules", "./src/index.js" ]

EXPOSE 4000

docker -compose.yml:

ex_dashboard:
  build: .
  ports:
  - "80:4000"
  volumes:
  - .:/usr/app/:rw
  environment:
  - NODE_ENV=dev
  command: >
    sh -c '
      if test -d node_modules; 
      then 
        echo node_modules_exists ; 
      else 
        cp -a /tmp/node_modules /usr/app/dashboard; 
      fi && 
      npm install && 
      /usr/local/bin/node --experimental-modules ./src/index.js
    '

Когда я запускаю docker-compose up, все идет хорошо, пока не возникнет эта ошибка:

ex_dashboard_1  | (node:18) ExperimentalWarning: The ESM module loader is experimental.
ex_dashboard_1  | file:///usr/app/src/index.js:9
ex_dashboard_1  |   <Provider store={store}>
ex_dashboard_1  |   ^
ex_dashboard_1  | 
ex_dashboard_1  | SyntaxError: Unexpected token '<'
ex_dashboard_1  |     at Loader.moduleStrategy (internal/modules/esm/translators.js:66:18)
ex_dashboard_1  |     at async link (internal/modules/esm/module_job.js:37:21)

Весь проект работает хорошо, если я просто запустил его npm start или собрал npm run build. Но я не знаю, почему это происходит в docker контейнере.

Вот package.json:

{
  "name": "explore_dashboard",
  "version": "1.0.0",
  "description": "A dashboard for the Explore project",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "cross-env NODE_ENV=development webpack-dev-server --hot",
    "build": "cross-env NODE_ENV=production webpack",
    "lint": "eslint ./src",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://gitlab.basalam.dev/data/explore_dashboard.git"
  },
  "author": "Gh.Sherafati",
  "license": "ISC",
  "resolve": {
    "alias": {
      "react-dom": "@hot-loader/react-dom"
    }
  },
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/plugin-transform-runtime": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "@babel/preset-react": "^7.8.3",
    "babel-eslint": "^10.0.3",
    "babel-loader": "^8.0.6",
    "cross-env": "^7.0.0",
    "css-loader": "^3.4.2",
    "eslint": "^6.1.0",
    "eslint-config-airbnb": "^18.0.1",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.0",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-react": "^7.18.0",
    "eslint-plugin-react-hooks": "^1.7.0",
    "html-webpack-plugin": "^3.2.0",
    "node-sass": "^4.13.1",
    "sass-loader": "^8.0.2",
    "style-loader": "^1.1.3",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.2"
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.27",
    "@fortawesome/free-solid-svg-icons": "^5.12.1",
    "@fortawesome/react-fontawesome": "^0.1.8",
    "@hot-loader/react-dom": "^16.11.0",
    "@types/react": "^16.9.19",
    "axios": "^0.19.2",
    "react": "^16.12.0",
    "react-beautiful-dnd": "^12.2.0",
    "react-dom": "^16.12.0",
    "react-hot-loader": "^4.12.19",
    "react-redux": "^7.1.3",
    "redux": "^4.0.5",
    "redux-saga": "^1.1.3"
  }
}

И webpack.config.js:

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const { env } = process;

module.exports = {
  entry: './src/index.js',
  mode: env.NODE_ENV,
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader', 'eslint-loader'],
      },
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          'style-loader',
          // Translates CSS into CommonJS
          'css-loader',
          // Compiles Sass to CSS
          'sass-loader',
        ],
      },
    ],
  },
  resolve: {
    extensions: ['*', '.js', '.jsx'],
  },
  output: {
    path: path.join(__dirname, '/build'),
    publicPath: '/',
    filename: 'bundle.js',
  },
  plugins: [
    new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(env.NODE_ENV) }),
    new HtmlWebpackPlugin({
      template: path.resolve('./src/index.html'),
    }),
  ],
  devServer: {
    contentBase: './build',
    hot: true,
  },
  devtool: env.NODE_ENV === 'development' ? 'cheap-module-eval-source-map' : undefined,
};

Также index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import App from './components/App';
import './scss/main.scss';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app'),
);

module.hot.accept();

Ответы [ 3 ]

0 голосов
/ 16 февраля 2020

В вашем docker-compose.yml файле удалите volumes: и довольно скучный command:.

. Здесь важно то, что ваш index.js файл на самом деле содержит конструкции JSX, которые Реагировать использует; это не просто Javascript и node не может запустить его напрямую. В вашем Dockerfile вас RUN webpack, что превращает это в обычный Javascript. volumes: перезаписывает все это любым содержимым вашей локальной системы; который не включает в себя этап транспирации, поэтому у вас нет действительного Javascript для запуска Node.

(Может потребоваться сделать явный вызов webpack в этом command:. Это предполагает ваш хост и контейнер node_modules совместимы, и он буквально дублирует все, что Dockerfile делает для создания образа в файле docker-compose.yml.)

Ничто не мешает вам установить Node в вашей хост-системе ( если у вас его еще нет), выполняйте живую разработку с использованием сервера разработки Webpack, а затем, используя Docker, на последнем этапе упаковки. Вероятно, это гораздо удобнее, чем внедрять систему изоляции, такую ​​как Docker, а затем пытаться обойти все ее функции для эмуляции локальной настройки разработки.

0 голосов
/ 16 февраля 2020

Наконец-то я решил проблему с помощью nginx и запустил версию сборки в контейнере, получив справку от этой замечательной статьи .

Новые Dockerfile и docker-compose.yml следует:

Dockerfile:

FROM node:12.14.1 as build
WORKDIR /app
COPY . /app
ENV PATH /app/node_modules/.bin:$PATH
RUN npm install
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

docker -compose.yml:

version: "3"
services:
  explore_dashboard:
    container_name: explore_dashboard
    build:
      context: .
      dockerfile:
        Dockerfile
    ports:
      - "8081:80"

nginx .conf:

server {
    listen 80;
    location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;
      try_files $uri $uri/ /index.html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
  }

Теперь я могу запустить приложение на http://127.0.0.1:8081/, работающем:

docker-compose up
0 голосов
/ 16 февраля 2020

Флаг --experimental-modules может использоваться для включения поддержки модулей ECMAScript (ES-модулей).

опция 1

CMD ["sh", "-c", "exec node --experimental-modules index.js"]

опция 2

CMD exec node --experimental-modules index.js

Полная документация:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...