Webpack 4: Module parse failed: Unexpected token - reactjs

During my builds, webpack is giving me this error:
ERROR in ./client/components/App/index.tsx 15:9
Module parse failed: Unexpected token (15:9)
You may need an appropriate loader to handle this file type.
|
|
> const App: SFC = () => (
| <div style={{ background: "red" }}>
| <h3>test</h3>
# ./client/index.tsx 11:4-14:6 12:24-51
# multi react-hot-loader/patch ./client/index.tsx webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true
Here is my webpack.config.ts:
import CleanWebpackPlugin from "clean-webpack-plugin";
import HtmlWebpackPlugin from "html-webpack-plugin";
import path from "path";
import { Configuration, HotModuleReplacementPlugin } from "webpack";
const rootDir = ["..", "..", "..", ".."];
const distDir = ["..", ".."];
// this file lives in one place as `.ts` and another as `.js` grab the
// file extension to determine the include path relative to its location
const include =
path.extname(module.id) === ".ts"
? path.resolve(__dirname, "client", "index.tsx")
: path.resolve(__dirname, ...rootDir, "client", "index.tsx");
const exclude = /node_modules/;
const tsconfig = path.resolve(
__dirname,
...rootDir,
"config",
"tsconfig.client.json"
);
// development plugins
const plugins = [
new HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "..", "..", "..", "index.html")
}),
new CleanWebpackPlugin([path.resolve(__dirname, ...distDir, "*.*")], {
allowExternal: true,
root: __dirname,
verbose: true
})
];
// script for webpack-hot-middleware
const hotMiddlewareScript: string =
"webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true";
const webpackDevConfig: Configuration = {
context: path.resolve(__dirname, ...rootDir),
devtool: "source-map",
entry: {
app: ["react-hot-loader/patch", include, hotMiddlewareScript]
},
mode: "development",
module: {
rules: [
{
exclude,
include,
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
exclude,
include,
loader: "ts-loader",
options: {
configFile: tsconfig,
transpileOnly: true
},
test: /\.tsx?$/
},
{
enforce: "pre",
exclude,
include,
loader: "source-map-loader",
test: /\.js$/
}
]
},
optimization: {
nodeEnv: "development"
},
output: {
filename: "[name].bundle.js",
path: path.join(__dirname, ...distDir),
publicPath: path.join(__dirname, ...distDir, "static/")
},
plugins,
resolve: {
extensions: [".js", ".ts", ".tsx", "*"]
},
target: "web"
};
export default webpackDevConfig;
My App.tsx:
import React, { SFC } from "react";
import ReactDOM from "react-dom";
const App: SFC = () => (
<div style={{ background: "red" }}>
<h3>test</h3>
</div>
);
My index.tsx:
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./components";
ReactDOM.render(<App />, document.getElementById("app"));
// enables Hot Module Replacement (HMR)
if ((module as any).hot) {
(module as any).hot.accept("./components/App", () => {
// for HMR to work, `App` must be re-required
const NextApp = require("./components/App").default;
ReactDOM.render(<NextApp />, document.getElementById("app"));
});
}
My tsconfig.json:
{
"compilerOptions": {
"allowJs": true,
"jsx": "react",
"module": "commonjs",
...
}
}
The error itself seems to give the solution: You may need an appropriate loader to handle this file type., however, it is my understanding that ts-loader should be able to handle react.
Here is an example webpack.config provided by the ts-loader team used in an app that uses typescript and react. The set up is fairly similar to my own, however, I do not use webpack-dev-server, rather, I use webpack-dev-middleware.

The issue was resolved by niba's comment on the original question. It seems that ts-loader when given a single module to include will not traverse the linked modules. Removing the include field or using the folder name fixed this error for me.

Related

How can I pull in an AngularJS app into a React host app Using Single-Spa

I'm hoping someone will be able to help.
I'm trying to use single-spa-angularjs to pull in a legacy AngularJS application into a React app. So the React app is the host. In the same React app, I'm also using Module Federation to pull in a separate React microfrontend.
So to sum it up, I have three apps:
React app - host and container
AngularJS app - legacy app using
AngularJS version 1.4.8
React microfrontend
All three apps are completely separate and hosted separately.
I was able to pull in the React microfrontend using Module Federation with no issues. The problem that I'm facing is pulling the AngularJS app into the host React app (app 1).
I'm getting a lot of errors in the console but I think this is the most relevant one:
xxx.js:701 Uncaught Error: application 'AngularJS' died in status LOADING_SOURCE_CODE: Module parse failed: Unexpected token (1:1)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!DOCTYPE html>
| <html lang="en" ng-app="MyAngularJSApp" ng-controller="MyAngularJSCtrl">
| <head>
at eval (index.html:1:7)
at ./index.html (node_modules_angularjs-bootstrap-datetimepicker_node_modules_moment_locale_sync_recursive_-no-1f57b2.app.bundle.js:27:1)
at __webpack_require__ (remoteEntry.js:44:42)
at eval (app.entry.js:21:69)
at ./app/app.entry.js (node_modules_angularjs-bootstrap-datetimepicker_node_modules_moment_locale_sync_recursive_-no-1f57b2.app.bundle.js:113:1)
at __webpack_require__ (remoteEntry.js:44:42)
at eval (container_entry:3:298)
at u.m.<computed> (bundle.js:2:262091)
at u (bundle.js:2:259451)
This is my current set up:
AngularJS App:
We're using webpack so we have a webpack.config.js file and the most important part is:
module.exports = function (env = {}) {
const isProd = !!env.prod;
const buildpath = env.buildpath ? env.buildpath : isProd ? 'dist' : 'build';
return {
entry: path.resolve(__dirname, 'app/app.entry.js'),
output: {
path: path.resolve(__dirname, buildpath),
filename: 'js/app.bundle.js',
clean: true,
},
plugins: [
new webpack.container.ModuleFederationPlugin({
name: 'MyAngularJSApp',
filename: 'remoteEntry.js',
remotes: {},
exposes: {
'./App': path.resolve(__dirname, 'app/app.entry.js'),
},
}),
new HtmlWebpackPlugin({
inject: 'body',
template: path.resolve(__dirname, 'index.html'),
filename: path.resolve(buildpath, 'index.html'),
})
],
module: {
......
},
resolve: {
......
},
optimization: {
......
},
};
};
In app/app.entry.js I've added the following:
import singleSpaAngularJS from 'single-spa-angularjs';
import angular from 'angular';
import app from '../index.html'
const domElementGetter = () => document.getElementById('AngularJSApp');
const ngLifecycles = singleSpaAngularJS({
angular: angular,
domElementGetter,
mainAngularModule: 'AngularJSApp',
template: app,
});
export const bootstrap = ngLifecycles.bootstrap;
export const mount = ngLifecycles.mount;
export const unmount = ngLifecycles.unmount;
In the host/consuming React application:
webpack.config.js:
const path = require('path');
const webpack = require('webpack')
const { ModuleFederationPlugin } = webpack.container;
const HtmlWebpackPlugin = require("html-webpack-plugin");
const dependencies = require('./package.json').dependencies;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
entry: './src/index.tsx',
mode: 'production',
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
exclude: /\.lazy\.html$/,
use: [
{
loader: 'html-loader',
options: {
minimize: true,
},
},
],
},
// Use Babel to transpile TypeScript and TypeScript / React files to ES5
{
test: /\.(tsx|ts)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new ModuleFederationPlugin({
name: 'container',
remotes: {
reactMFE: 'reactMFE#http://localhost:3000/remoteEntry.js',
AngularJSApp: 'AngularJSApp#http://localhost:3004/remoteEntry.js',
},
shared: {
react: {
singleton: true,
eager: true,
requiredVersion: dependencies.react,
},
'react-dom': {
singleton: true,
eager: true,
requiredVersion: dependencies['react-dom'],
}
},
}),
new webpack.DefinePlugin({ // <-- key to reducing React's size
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
// new BundleAnalyzerPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
I've registered the Angular app in the entry point /src/index.tsx. The same file also imports 'bootstrap' to resolve the eager consumption error when using module federation:
/src/index.tsx:
import("./bootstrap")
import {registerApplication} from 'single-spa'
registerApplication(
'AngularJSApp',
//#ts-ignore
() => import('AngularJSApp/App'),
location => location.pathname.startsWith('/')
)
/src/bootstrap.tsx:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { App } from './App'
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
I've made changes to load in the scripts for the imported apps in public/index.html:
<html>
<head>
<script src="http://localhost:3000/remoteEntry.js"></script>
<script src="http://localhost:3004/remoteEntry.js"></script>
</head>
<body>
<div>Container App</div>
<div id="root"></div>
{/* I've put these two lines as a last ditch attempt - not sure which one of them should be working*/}
<div id="AngularJSApp"></div>
<div id="single-spa-application:AngularJSApp"></div>
</body>
</html>
Can someone advise on how I can get this working, it would be much appreciated.
Thank you

Switching from NPM to PNPM - Absolute File Paths Break in React Project

So npm was getting really slow for CircleCi and my builds were timing out and running into memory issues. So I wanted to switch to pnpm. Upon switching to pnpm I noticed that any .js file in my react project that are using an absolute path no longer work and wants me to turn them all into relative paths. Not sure if this is a bug with the version or I'm doing something wrong but it all i did was delete my package-lock.json and deleted my node_modules and installed pnpm#5 then ran pnpm i and then built my project as I've always done
npm -v 6.13.4
node -v 12.16.0
pnpm -v 5.18.0
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
Error has occured: ModuleNotFoundError: Module not found: Error: Can't resolve 'Root' in '/Users/Olive/dashboard/src'
Parsed request is a module
using description file: /Users/Olive/dashboard/package.json (relative path: ./src)
resolve as module
/Users/Olive/dashboard/src/node_modules doesn't exist or is not a directory
/Users/Olive/node_modules doesn't exist or is not a directory
/Users/node_modules doesn't exist or is not a directory
/Users/node_modules doesn't exist or is not a directory
/node_modules doesn't exist or is not a directory
looking for modules in /Users/Olive/dashboard/node_modules
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules)
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules/Root)
no extension
/Users/Olive/dashboard/node_modules/Root doesn't exist
.web.js
/Users/Olive/dashboard/node_modules/Root.web.js doesn't exist
.mjs
/Users/Olive/dashboard/node_modules/Root.mjs doesn't exist
.js
/Users/Olive/dashboard/node_modules/Root.js doesn't exist
.json
/Users/Olive/dashboard/node_modules/Root.json doesn't exist
.web.jsx
/Users/Olive/dashboard/node_modules/Root.web.jsx doesn't exist
.jsx
/Users/Olive/dashboard/node_modules/Root.jsx doesn't exist
as directory
/Users/Olive/dashboard/node_modules/Root doesn't exist
looking for modules in /Users/Olive/dashboard/node_modules
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules)
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules/Root)
no extension
/Users/Olive/dashboard/node_modules/Root doesn't exist
.web.js
/Users/Olive/dashboard/node_modules/Root.web.js doesn't exist
.mjs
/Users/Olive/dashboard/node_modules/Root.mjs doesn't exist
.js
/Users/Olive/dashboard/node_modules/Root.js doesn't exist
.json
/Users/Olive/dashboard/node_modules/Root.json doesn't exist
.web.jsx
/Users/Olive/dashboard/node_modules/Root.web.jsx doesn't exist
.jsx
/Users/Olive/dashboard/node_modules/Root.jsx doesn't exist
as directory
/Users/Olive/dashboard/node_modules/Root doesn't exist
Before
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import registerServiceWorker from 'registerServiceWorker';
import Root from 'Root';
ReactDOM.render(
<BrowserRouter>
<Root/>
</BrowserRouter>,
document.getElementById('root'));
registerServiceWorker();
After: What it wants me to do to my absolute paths -> relative paths
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import registerServiceWorker from './registerServiceWorker'; // Changed this
import Root from './Root'; // Changed this
ReactDOM.render(
<BrowserRouter>
<Root/>
</BrowserRouter>,
document.getElementById('root'));
registerServiceWorker();
webpack file
'use strict';
const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
const publicPath = '/';
const publicUrl = '';
const env = getClientEnvironment(publicUrl);
module.exports = {
devtool: 'cheap-module-source-map',
entry: [
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
],
mode: 'development',
output: {
pathinfo: true,
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
},
resolve: {
modules: ['node_modules', paths.appNodeModules].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
'react-native': 'react-native-web',
},
plugins: [
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
],
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{
oneOf: [
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
plugins: [
["syntax-async-functions"],
["#babel/plugin-proposal-decorators", { "legacy": true}],
]
},
},
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
flexbox: 'no-2009',
}),
],
},
},
],
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
new webpack.DefinePlugin(env.stringified),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
performance: {
hints: false,
},
};
module.exports.parallelism = 1;
jsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"baseUrl": "src"
},
"include": [
"src"
]
}
I'm also getting this warning which I wasn't getting when using npm
ExperimentalWarning: Package name self resolution is an experimental feature. This feature could change at any time
With yarn I also get the same error as above, but then this special failure
./node_modules/enzyme/node_modules/htmlparser2/lib/esm/index.js 59:9
Module parse failed: Unexpected token (59:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| return getFeed(parseDOM(feed, options));
| }
> export * as DomUtils from "domutils";
| // Old name for DomHandler
| export { DomHandler as DefaultHandler };
https://github.com/cheeriojs/cheerio/issues/2545
This did not work

Why is this react-hot-loader not working I get error about loaders when they call rules

I followed this how-to-add-hot-module-reloading-to-a-react-app but get an error.
I know this is an easy one because i'm new to this. Also most tutorials are so out of date so its hard to find something consistent to learn this
I think the webpack server is ok and can be started ok
Please advice:
ERROR in ./src/index.js 5:16
Module parse failed: Unexpected token (5:16)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import App from "./App";
|
> ReactDOM.render(<App />, document.getElementById("root"));
Here's webpack.config.js
const webpack = require('webpack');
const port = process.env.PORT || 3000;
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
],
rules: [
{
test: /\.json$/,
loader: 'json-loader'
}
],
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true
},
devServer: {
host: 'localhost',
port: port,
historyApiFallback: true,
open: true
}
};
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
UPDATE
Adding App.js
import React, { Component } from "react";
import Header from "./components/structure/Header";
import Content from "./components/structure/Content";
import Footer from "./components/structure/Footer";
import Resume from "./resume.json";
import { hot } from 'react-hot-loader/root'
class App extends Component {
componentDidMount() {
document.title = [
Resume.basics.name,
Resume.basics.label,
[Resume.basics.location.region, Resume.basics.location.country].join(", ")
].join(" | ");
}
render() {
return (
<div>
<Header />
<Content />
<Footer />
</div>
);
}
}
export default hot(App)
Also get this error now .babelrc cant find schema:

React - kendo-ui styles module failed to parse - You may need an appropriate loader to handle this file type

I need to import default Kendo-ui template styles from this site https://www.telerik.com/kendo-react-ui/components/styling/.
When it trying to load styles, it throws NodeInvocationException: Prerendering failed because of error: Error: Module parse failed: "project folder"\node_modules\#progress\kendo-theme-default\dist\all.css Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
Here is my layout.ts file where I want to import style template
import * as React from 'react';
import { NavMenu } from './NavMenu';
import "#progress/kendo-theme-default/dist/all.css";
export class Layout extends React.Component<{}, {}> {
public render() {
return <div className='container-fluid'>
<div className='row'>
<div className='col-sm-3'>
<NavMenu />
</div>
<div className='col-sm-9'>
{ this.props.children }
</div>
</div>
</div>;
}
}
webpack.config looks like this, its default configuration from auto generated react-redux asp.net project
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const merge = require('webpack-merge');
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
// Configuration in common to both client-side and server-side bundles
const sharedConfig = () => ({
stats: { modules: false },
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
filename: '[name].js',
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
plugins: [new CheckerPlugin()]
});
// Configuration for client-side bundle suitable for running in browsers
const clientBundleOutputDir = './wwwroot/dist';
const clientBundleConfig = merge(sharedConfig(), {
entry: { 'main-client': './ClientApp/boot-client.tsx' },
module: {
rules: [
{ test: /\.css$/, use: ExtractTextPlugin.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) }
]
},
output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [
new ExtractTextPlugin('site.css'),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin()
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
const serverBundleConfig = merge(sharedConfig(), {
resolve: { mainFields: ['main'] },
entry: { 'main-server': './ClientApp/boot-server.tsx' },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./ClientApp/dist/vendor-manifest.json'),
sourceType: 'commonjs2',
name: './vendor'
})
],
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
devtool: 'inline-source-map'
});
return [clientBundleConfig, serverBundleConfig];
};
In order for the external .css files to work ( like kendo-theme-default coming from node_modules ), a postcss-loader is required.

VS2017: Using JSX components from react theme in ASP.NET Core React Redux web application template

I've created a project using Visual Studio 2017 preview using the ASP.NET Core "React.js and Redux" project type.
I'm now trying to include components from a theme and we're running into some issues I haven't been able to resolve with extensive googling. I suspect I am misunderstanding how to use webpack. I've boiled it down to an extremely simple test case below.
Note: I have "allowJs": true in my tsconfig.json because it complains about not having the --allowJs flag when I try to import a jsx file otherwise.
This issue looks suspiciously similar to this issue: import jsx file in tsx compilation error but I believe this one is distinct and googling hasn't gotten me anywhere.
What I've tried:
setting "jsx" to "react", "react-native", and "preserve"
creating separate rule under sharedConfig in webpack.config.js (probably incorrectly?)
adding a rule for jsx and installing babel-core
Changing settings more or less at random in tsconfig.json and webpack.config.js
Too much googling
the error:
NodeInvocationException: Prerendering failed because of error: Error: Module parse failed: D:\MyProject\ClientApp\components\Card.jsx Unexpected token (5:12)
You may need an appropriate loader to handle this file type.
| render(){
| return (
| <div> Test </div>
| );
| }
at Object.<anonymous> (D:\MyProject\ClientApp\dist\main-server.js:21692:7)
at __webpack_require__ (D:\MyProject\ClientApp\dist\main-server.js:20:30)
at Object.<anonymous> (D:\MyProject\ClientApp\dist\main-server.js:8547:64)
at __webpack_require__ (D:\MyProject\ClientApp\dist\main-server.js:20:30)
at Object.<anonymous> (D:\MyProject\ClientApp\dist\main-server.js:8445:75)
at __webpack_require__ (D:\MyProject\ClientApp\dist\main-server.js:20:30)
at Object.<anonymous> (D:\MyProject\ClientApp\dist\main-server.js:8498:66)
at __webpack_require__ (D:\MyProject\ClientApp\dist\main-server.js:20:30)
at D:\MyProject\ClientApp\dist\main-server.js:66:18
at Object.<anonymous> (D:\MyProject\ClientApp\dist\main-server.js:69:10)
Current directory is: D:\MyProject
Home.tsx
import * as React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { ApplicationState } from '../store';
import Card from './Card';
type HomeProps = RouteComponentProps<{}>;
export default class Home extends React.Component<RouteComponentProps<{}>, {}> {
public render() {
return <div>
<Card></Card>
</div>
}
}
Card.jsx
import React, { Component } from 'react';
class Card extends Component{
render(){
return (
<div> Test </div>
);
}
}
export default Card;
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const merge = require('webpack-merge');
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
// Configuration in common to both client-side and server-side bundles
const sharedConfig = () => ({
stats: { modules: false },
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
filename: '[name].js',
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
plugins: [new CheckerPlugin()]
});
// Configuration for client-side bundle suitable for running in browsers
const clientBundleOutputDir = './wwwroot/dist';
const clientBundleConfig = merge(sharedConfig(), {
entry: { 'main-client': './ClientApp/boot-client.tsx' },
module: {
rules: [
{ test: /\.css$/, use: ExtractTextPlugin.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) }
]
},
output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [
new ExtractTextPlugin('site.css'),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin()
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
const serverBundleConfig = merge(sharedConfig(), {
resolve: { mainFields: ['main'] },
entry: { 'main-server': './ClientApp/boot-server.tsx' },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./ClientApp/dist/vendor-manifest.json'),
sourceType: 'commonjs2',
name: './vendor'
})
],
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
devtool: 'inline-source-map'
});
return [clientBundleConfig, serverBundleConfig];
};
tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"module": "es2015",
"moduleResolution": "node",
"target": "es5",
"jsx": "react",
"experimentalDecorators": true,
"sourceMap": true,
"skipDefaultLibCheck": true,
"strict": true,
"lib": ["es6", "dom"],
"types": [ "webpack-env" ],
"allowJs": true
},
"exclude": [
"bin",
"node_modules"
]
}
To fix this we had to add some stuff to package.json and webpack to support babel loader. This hasn't been working perfectly, but it's gotten us a step closer to having things work properly. This is due to some unresolved typing issues.
Package.json
"babel-core":"6.26.0",
"babel-loader": "7.1.4",
"babel-preset-es2015": "6.24.1",
"babel-preset-react": "6.24.1",
Webpack.config.js:
module: {
rules: [
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.(png|jpg|jpeg|gif)$/, use: 'url-loader?limit=25000' },
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['react', 'es2015']
}
}
]
},

Resources