Babel не может анализировать файлы, используя Flow из локального пользовательского модуля.Сбой со следующей ошибкой: `Сборка модуля не удалась ... SyntaxError: Неожиданный токен` - PullRequest
0 голосов
/ 16 апреля 2019

Итак, я создаю веб-приложение, мы назовем WebApp, который является модулем React, который использует компоненты из пользовательского модуля React, мы назовем CustomModule, который также находится на моем локальном компьютере. , Я пытался импортировать определенные компоненты из CustomModule в WebApp и столкнулся со следующей ошибкой, которая появляется при запуске webpack-dev-server -d в WebApp:

ERROR in /CustomModule/Components/LoadingSpinner/LoadingSpinner.jsx
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /CustomModule/Components/LoadingSpinner/LoadingSpinner.jsx: Unexpected token, expected ";" (11:17)

   9 |
  10 | export const Spinner = () => {
> 11 |     var imgStyle : object = {
     |                  ^
  12 |         height:"75%",
  13 |         padding:"2px 0 0 2px"
  14 |     } ;
    at Parser.raise (/WebApp/node_modules/@babel/parser/lib/index.js:3851:17)
    at Parser.unexpected (/WebApp/node_modules/@babel/parser/lib/index.js:5167:16)
    at Parser.semicolon (/WebApp/node_modules/@babel/parser/lib/index.js:5149:40)
    at Parser.parseVarStatement (/WebApp/node_modules/@babel/parser/lib/index.js:7763:10)
    at Parser.parseStatementContent (/WebApp/node_modules/@babel/parser/lib/index.js:7358:21)
    at Parser.parseStatement (/WebApp/node_modules/@babel/parser/lib/index.js:7291:17)
    at Parser.parseBlockOrModuleBlockBody (/WebApp/node_modules/@babel/parser/lib/index.js:7868:25)
    at Parser.parseBlockBody (/WebApp/node_modules/@babel/parser/lib/index.js:7855:10)
    at Parser.parseBlock (/WebApp/node_modules/@babel/parser/lib/index.js:7839:10)
    at Parser.parseFunctionBody (/WebApp/node_modules/@babel/parser/lib/index.js:6909:24)
 @ /CustomModule/Components/LoadingSpinner/index.js 1:0-65 1:0-65
 @ /CustomModule/Components/index.js
 @ ./ClientScripts/DataExplorer/Dashboard/containers/DashboardContent.jsx
 @ ./ClientScripts/DataExplorer/Dashboard/index.js
 @ ./ClientScripts/Route/RouteConfig.jsx
 @ ./ClientScripts/Route/index.js
 @ ./ClientScripts/Main.jsx
 @ ./ClientScripts/index.js
 @ multi (webpack)-dev-server/client?http://localhost:9000 ./ClientScripts/index.js

Оба модуля используют Flow, babel и webpack. Я настроил файлы package.json, webpack.config.js, .flowconfig и .babelrc соответственно в каждом модуле. Затем я символически связал CustomModule с WebApp, используя npm link. Я строю CustomModule, используя webpack, затем пытаюсь построить WebApp, который содержит оператор импорта для использования компонента из CustomModule.

Версия

node: v9.0.0
npm: 5.5.1

@babel/cli: 7.2.3
@babel/core: 7.4.3
@babel/preset-flow: 7.0.0
babel-loader: 8.0.5
flow: 0.2.3
flow-webpack-plugin: 1.2.0
webpack: 4.16.5

WebApp webpack.config.js

const webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const FlowWebpackPlugin = require('flow-webpack-plugin');

module.exports = {
  entry: {
    vendor: ['babel-polyfill', 'react', 'react-dom'],
    annotationService: glob.sync('./ClientScripts/AnnotationService/*.js'),
    repositoryService: glob.sync('./ClientScripts/RepositoryService/*.js'),
    timelineService: glob.sync('./ClientScripts/TimelineService/*.js'),
    filterService: glob.sync('./ClientScripts/DataExplorer/Dashboard/FilterServices/*.js'),
    platform: './ClientScripts/index.js',
    objects: glob.sync("./ClientScripts/RepositoryService/Objects/*.js"),
    sass: './sass/main.scss'
  },
  output: {
    path: path.join(__dirname, 'reactDist'),
    filename: 'js/[name].js',
    sourceMapFilename: 'map/[name].map'
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  },
  resolve: {
    alias: {
      Interfaces: path.resolve(__dirname, 'ClientScripts/Interfaces/'),
      Layout: path.resolve(__dirname, 'ClientScripts/Layout/'),
      Navigation: path.resolve(__dirname, 'ClientScripts/Navigation/'),
      Redux: path.resolve(__dirname, 'ClientScripts/Redux/'),
      RepositoryService: path.resolve(__dirname, 'ClientScripts/RepositoryService/'),
      TimelineService: path.resolve(__dirname, 'ClientScripts/TimelineService/'),
      FilterService: path.resolve(__dirname, 'ClientScripts/DataExplorer/Dashboard/FilterServices/'),
      AnnotationService: path.resolve(__dirname, 'ClientScripts/AnnotationService/'),
      Route: path.resolve(__dirname, 'ClientScripts/Route/'),
      Timeline: path.resolve(__dirname, 'ClientScripts/Timeline/'),
      TimelineEditor: path.resolve(__dirname, 'ClientScripts/TimelineEditor/'),
      Utilities: path.resolve(__dirname, 'ClientScripts/jsutils/'),
      ReactUtils: path.resolve(__dirname, 'ClientScripts/reactUtils/'),
      Images: path.resolve(__dirname, 'img/'),
    },
    symlinks: true
  },
  target: 'web',
  node: {
    fs: "empty"
  },
  externals: {
    'winston': 'require("winston")
  },
  module: {
    rules: [
      { test: /\.js$/, loader: 'babel-loader' },
      { test: /\.jsx$/, loader: 'babel-loader' },
      { test: /\.env$/, loader: "file-loader?name=index.[ext]", exclude: [/node_modules/] },
      {
        test: /\.scss$|\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          use: [{
            loader: "css-loader",
            options: {
              minimize: true
            }
          },'sass-loader']
        })
      },
      { test: /\.(jpe?g|png|gif|svg)$/,
        loader: 'file-loader?name=img/[name].[ext]?',
        options: {
          name (file) {
            if (process.env.environment === 'prod') {
              return '[path][name].[hash].[ext]'
            }

            return '[path][name].[ext]'
          }
        }
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({ filename: 'css/timeline.[md5:contenthash:hex:20].css', disable: false, allChunks: true }),
    new FlowWebpackPlugin()
  ]
}

WebApp .flowconfig

[ignore]
.*/node_modules/flow-webpack-plugin/.*
.*/node_modules/.*\.json$
.*/node_modules/\.staging/.*

[libs]
flow-typed

[options]
module.name_mapper='^Interfaces\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/Interfaces/\1'
module.name_mapper='^Layout\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/Layout/\1'
module.name_mapper='^Navigation\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/Navigation/\1'
module.name_mapper='^Redux\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/Redux/\1'
module.name_mapper='^RepositoryService\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/RepositoryService/\1'
module.name_mapper='^Route\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/Route/\1'
module.name_mapper='^Timeline\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/Timeline/\1'
module.name_mapper='^TimelineEditor\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/TimelineEditor/\1'
module.name_mapper='^Utilities\/\(.*\)$' -> '<PROJECT_ROOT>/ClientScripts/jsutils/\1'
module.name_mapper='^Images\/\(.*\)$' -> '<PROJECT_ROOT>/img/\1'
module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.svg
module.file_ext=.json

CustomModule webpack.config.js

const webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const FlowWebpackPlugin = require('flow-webpack-plugin');

module.exports = {
  entry: {
    vendor: ['babel-polyfill', 'react', 'react-dom'],
    components: './Components/index.js',
    sass: './sass/main.scss'
  },
  output: {
    path: path.join(__dirname, 'reactDist'),
    filename: 'js/[name].js',
    sourceMapFilename: 'map/[name].map'
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  },
  resolve: {
    alias: {
      Components: path.resolve(__dirname, 'Components/'),
      Images: path.resolve(__dirname, 'img/'),
      Utilities: path.resolve(__dirname, 'Utilities/')
    },
    // extensions: ['', '.js', '.jsx']
  },
  target: 'web',
  node: {
    fs: "empty"
  },
  externals: {
    'winston': 'require("winston")'
  },
  module: {
    rules: [
      { test: /\.js$/, loader: 'babel-loader', exclude: [/node_modules/] },
      {
        test: /\.jsx$/,
        loader: 'babel-loader',
        exclude: [/node_modules/],
        query: {
          presets: ['@babel/preset-flow']
        }
      },
      { test: /\.env$/, loader: "file-loader?name=index.[ext]", exclude: [/node_modules/] },
      {
        test: /\.scss$|\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          use: [{
            loader: "css-loader",
            options: {
              minimize: true
            }
          },'sass-loader']
        })
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/,
        loader: 'file-loader?name=img/[name].[ext]?',
        options: {
          name (file) {
            if (process.env.environment === 'prod') {
              return '[path][name].[hash].[ext]'
            }

            return '[path][name].[ext]'
          }
        }
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({ filename: 'css/timeline.[md5:contenthash:hex:20].css', disable: false, allChunks: true }),
    new FlowWebpackPlugin(),
  ]
}

CustomModule .flowconfig

[ignore]
.*/node_modules/flow-webpack-plugin/.*
.*/node_modules/.*\.json$
.*/node_modules/\.staging/.*

[libs]
flow-typed

[options]
module.name_mapper='^Components\/\(.*\)$' -> '<PROJECT_ROOT>/Components/\1'
module.name_mapper='^Images\/\(.*\)$' -> '<PROJECT_ROOT>/img/\1'
module.name_mapper='^Utilities\/\(.*\)$' -> '<PROJECT_ROOT>/Utilities/\1'
module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.svg
module.file_ext=.json

Один и тот же файл .babelrc используется для обоих модулей

/*
    ./.babelrc
*/
{
    "presets":[
        "@babel/preset-env", "@babel/preset-react", "@babel/preset-flow"
    ],
    "plugins": [
        "@babel/plugin-syntax-dynamic-import",
        "@babel/plugin-syntax-import-meta",
        "@babel/plugin-transform-flow-strip-types",
        "@babel/plugin-proposal-class-properties",
        "@babel/plugin-proposal-json-strings",
        [
            "@babel/plugin-proposal-decorators",
            {
                "legacy": true
            }
        ],
        "@babel/plugin-proposal-function-sent",
        "@babel/plugin-proposal-export-namespace-from",
        "@babel/plugin-proposal-numeric-separator",
        "@babel/plugin-proposal-throw-expressions"
    ]
}

Я ожидаю, что результат webpack-dev-server не даст никаких ошибок вместо Module build failed ошибки, которая выдается выше при разборе babel.

1 Ответ

0 голосов
/ 16 апреля 2019
Плагин

Webpack babel не может проанализировать объявление объекта imgStyle в вашем пользовательском файле LoadingSpinner.jsx.Это связано с тем, что для вашего объекта стиля для вашего счетчика в объявлении объекта стиля проскальзывает :. Это приводит к ошибке синтаксического анализа , так как это недопустимый синтаксис JavaScript поэтому вы получаете следующую синтаксическую ошибку:

SyntaxError: /CustomModule/Components/LoadingSpinner/LoadingSpinner.jsx: неожиданный токен, ожидается ";"(11:17)

Глядя на трассировку стека, он указывает, что строка 11 является виновником:

  10 | export const Spinner = () => {
> 11 |     var imgStyle : object = {
     |                  ^
  12 |         height:"75%",
  13 |         padding:"2px 0 0 2px"
  14 |     } ;

Обратите внимание на эту строку: var imgStyle : object = { // extra colon before the object declaration

Просто удалите : в своем объявлении объекта в стиле спиннера, и плагин webpack babel теперь сможет успешно анализировать этот файл.Примерно так:

var imgStyleObject = {
   height:"75%",
   padding:"2px 0 0 2px"
};

Надеюсь, это поможет!

...