0

所以我正在创建一个 web 应用程序,我们将调用WebApp它,它是一个使用来自自定义 React 模块的组件的 React 模块,我们将调用CustomModule它,它也位于我的本地计算机上。我一直在尝试从CustomModulein导入某些组件,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,babelwebpack. 我已经在每个模块中相应地设置了package.jsonwebpack.config.js.flowconfig和文件。.babelrc然后我象征性地链接CustomModuleWebAppusing npm link。我构建CustomModuleusingwebpack然后尝试构建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

自定义模块 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(),
  ]
}

自定义模块 .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 解析期间抛出的错误。

4

1 回答 1

1

Webpackbabel插件无法解析imgStyle自定义LoadingSpinner.jsx文件中的对象声明。这是因为您的样式对象,对于您的微调器,:在您的样式对象声明中滑倒了。这会导致解析错误 ,因为这不是有效的JavaScript语法,因此您会收到以下语法错误:

SyntaxError: /CustomModule/Components/LoadingSpinner/LoadingSpinner.jsx: Unexpected token, expected ";" (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

:只需在您的自定义微调样式对象声明中删除 ,webpackbabel插件现在应该能够成功解析此文件。类似于以下内容:

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

希望这会有所帮助!

于 2019-04-16T19:27:32.730 回答