Reputation: 31
So I'm creating a web app, we'll call WebApp
, which is a React module that uses components from a custom React module, we'll call CustomModule
, that is also located on my local machine. I've been trying to import certain components from CustomModule
in WebApp
and have been running into the following error that appears when running webpack-dev-server -d
in 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
Both modules use Flow
, babel
, and webpack
. I've set up the package.json
, webpack.config.js
, .flowconfig
, and .babelrc
files accordingly in each module. Then I symbolically linked CustomModule
to WebApp
using npm link
. I build the CustomModule
using webpack
then attempt to build the WebApp
which contains an import statement to use a component from CustomModule
.
Versions
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
The same .babelrc is used for both modules
/*
./.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"
]
}
I expect the result of the webpack-dev-server
to yield no errors instead of the Module build failed
error that is thrown above during babel parsing.
Upvotes: 0
Views: 785
Reputation: 8151
Webpack
's babel
plugin is failing to parse your imgStyle
object declaration within your custom LoadingSpinner.jsx
file. This is because your style object, for your spinner, has a :
slipped within your style object declaration.. This causes a parsing error since this isn't valid JavaScript
syntax so you're getting the following syntax error:
SyntaxError: /CustomModule/Components/LoadingSpinner/LoadingSpinner.jsx: Unexpected token, expected ";" (11:17)
Looking at the stack trace, it points out that line 11 is the culprit:
10 | export const Spinner = () => {
> 11 | var imgStyle : object = {
| ^
12 | height:"75%",
13 | padding:"2px 0 0 2px"
14 | } ;
Notice this line:
var imgStyle : object = { // extra colon before the object declaration
Just remove the :
within your custom spinner-style object declaration and webpack
's babel
plugin should now be able to successfully parse this file. Something like the following:
var imgStyleObject = {
height:"75%",
padding:"2px 0 0 2px"
};
Hopefully that helps!
Upvotes: 1