I am attempting to add automated testing to a react application using karma and mocha. The application is written using ES6 and JSX so I am also using webpack. I have imported the webpack config into the karma configuration settings, but I am still getting an error whenever I try to render a JSX component for testing:
Uncaught Error: Module parse failed: C:\Users\blahblahblah\app\tests\components\Clock.test.jsx Unexpected token (18:47)
You may need an appropriate loader to handle this file type.
| let testTime = 100;
| let expected = '00:01:40';
| let clock = TestUtils.renderIntoDocument(<Clock />);
| let actual = clock.formatTime(testTime);
|
at app/tests/components/Clock.test.jsx:74
Here are the files in question:
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VENDOR_LIBS = [
'axios', 'react', 'react-dom',
'react-loading', 'react-router', 'moment'
];
module.exports = {
entry: {
bundle: [
'script-loader!jquery/dist/jquery.min.js',
'script-loader!foundation-sites/dist/js/foundation.min.js',
'./app/app.jsx',
], // compile app files to bundle.js
vendor: VENDOR_LIBS // compile vendor files to vendor.js
},
externals: {
jquery: 'jQuery'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
resolve: {
alias: {
appStyles: path.resolve(__dirname, 'app/styles/app.scss'),
Main: path.resolve(__dirname, 'app/components/Main.jsx'),
Nav: path.resolve(__dirname, 'app/components/Nav.jsx'),
Timer: path.resolve(__dirname, 'app/components/Timer.jsx'),
Countdown: path.resolve(__dirname, 'app/components/Countdown.jsx'),
Clock: path.resolve(__dirname, 'app/components/Clock.jsx'),
Controls: path.resolve(__dirname, 'app/components/Controls.jsx')
},
extensions: [".js", ".jsx"]
},
module: {
rules: [
{
use: 'babel-loader',
test: /\.jsx?$/,
exclude: /node_modules/
},
{
use: ['style-loader', 'css-loader', 'sass-loader'],
test: /\.scss$/
},
{
use: ['style-loader', 'css-loader'],
test: /\.css$/
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
new HtmlWebpackPlugin({
template: './app/index.html'
}),
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery'
})
],
devtool: 'cheap-module-eval-source-map'
}
karma.conf.js
const webpackConfig = require('./webpack.config.js');
module.exports = (config) => {
config.set({
browsers: ['Chrome'],
singleRun: true,
frameworks: ['mocha'],
files: ['app/tests/**/*.test.jsx'],
preprocessors: {
'app/tests/**/*.test.jsx': ['webpack', 'sourcemap']
},
reporters: ['mocha'],
client: {
mocha: { // after 5 seconds, if a test hasnt finished, cancel it
timeout: '5000'
},
webpack: webpackConfig, // use our established webpack config
webpackServer: {
noInfo: true
}
}
})
}
package.json
{
"name": "boilerplate",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "karma start",
"clean": "rimraf dist",
"build": "SET NODE_ENV=production npm run clean & webpack -p",
"serve": "webpack-dev-server"
},
"author": "",
"license": "MIT",
"dependencies": {
"axios": "^0.16.1",
"express": "^4.15.2",
"moment": "^2.18.1",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-loading": "0.0.9",
"react-router": "^3.0.0"
},
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^6.4.1",
"babel-preset-env": "^1.1.4",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-0": "^6.24.1",
"colors": "^1.1.2",
"css-loader": "^0.28.1",
"expect": "^1.20.2",
"foundation-sites": "^6.3.1",
"html-webpack-plugin": "^2.28.0",
"jquery": "^3.2.1",
"karma": "^1.7.0",
"karma-chrome-launcher": "^2.1.1",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.3",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.3",
"mocha": "^3.4.1",
"node-sass": "^4.5.3",
"react-addons-test-utils": "^15.5.1",
"rimraf": "^2.6.1",
"sass-loader": "^6.0.5",
"script-loader": "^0.7.0",
"style-loader": "^0.17.0",
"webpack": "^2.3.3",
"webpack-dev-middleware": "^1.10.2",
"webpack-dev-server": "^2.4.5"
}
}
.babelrc
{
"presets": ["react", "es2015", "stage-0"]
}
The test that keeps failing:
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-dom/test-utils';
import expect from 'expect';
import $ from 'jQuery';
// Karma not recognizing webpack aliases
import Clock from 'babel-loader!./../../components/Clock.jsx';
describe('Clock Component', () => {
it('should exist', () => {
expect(Clock).toExist();
});
// THIS TEST KEEPS FAILING
describe('formatSeconds()', () => {
it('should format seconds to hh:mm:ss', () => {
let testTime = 100;
let expected = '00:01:40';
let clock = TestUtils.renderIntoDocument(<Clock />); // JSX = problem
let actual = clock.formatTime(testTime);
expect(actual).toBe(expected);
});
});
});
Related
Background
Need to create an external React component library using existing components from a Next.js site, using Tailwindcss#^2. This needs to be pulled in using npm, onto any site that requires the components.
Problem
I've managed to create the package using Webpack#^5 to compile. This is all fine, but the problem I face is that, the components don't work when reintroduced to the initial site. I have a feeling this is either the compiling is wrong or the fact that Next.js is server side rendered, or it could be both.
Attempted solution
I have tried to use Rollup as an alternate solution to compile the components, but I keep running into an issue with Postcss. A common issue I've noticed, where it's asking for v8 of PostCss (which it appears is present in node_modules), but it still complains. I did have a similar issue when using Webpack, but was eventually able to fix this. I've tried similar methods to fix for Rollup, but no luck.
package.json
{
"name": "#github_account/package_name",
"description": "Lorem ipsum",
"author": "github_account",
"version": "1.0.0",
"license": "ISC",
"repository": {
"type": "git",
"url": "repo_name_here"
},
"main": "./build/main.cjs.js",
"module": "./build/main.esm.js",
"browser": "./build/main.js",
"source": "./src/index.js",
"publishConfig": {
"registry": "https://npm.pkg.github.com/github_account"
},
"scripts": {
"build-rollup": "rollup -c",
"build": "webpack --mode production"
},
"dependencies": {
"#babel/runtime": "^7.17.8",
"autoprefixer": "^9.8.8",
"classnames": "^2.2.6",
"formik": "^2.2.6",
"iframe-resizer-react": "^1.1.0",
"luxon": "^2.0.2",
"prop-types": "^15.8.1",
"react": "^17.0.0",
"react-collapsible": "^2.8.4",
"react-device-detect": "^2.1.2",
"react-dom": "^17.0.0",
"react-google-recaptcha-v3": "^1.9.7",
"react-icons": "^3.10.0",
"react-markdown": "^6.0.3",
"react-modal": "^3.14.4",
"react-select": "^5.0.0",
"react-slick": "^0.28.1",
"react-table": "^7.7.0",
"sass": "^1.42.1",
"slick-carousel": "^1.8.1",
"yup": "^0.32.8"
},
"devDependencies": {
"#babel/core": "^7.18.6",
"#babel/plugin-syntax-jsx": "^7.18.6",
"#babel/plugin-transform-runtime": "^7.18.9",
"#babel/preset-env": "^7.18.6",
"#babel/preset-react": "^7.18.6",
"#rollup/plugin-babel": "^5.3.1",
"#rollup/plugin-commonjs": "^22.0.1",
"#rollup/plugin-node-resolve": "^13.3.0",
"#squoosh/lib": "^0.4.0",
"autoprefixer": "~9",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.2.5",
"clean-webpack-plugin": "^4.0.0",
"cross-env": "^7.0.2",
"css-loader": "^6.7.1",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.7.0",
"eslint-config-standard": "^14.1.0",
"eslint-config-standard-react": "^9.2.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.17.0",
"eslint-plugin-standard": "^4.0.1",
"image-minimizer-webpack-plugin": "^3.2.3",
"microbundle-crl": "^0.13.11",
"mini-css-extract-plugin": "^2.6.1",
"next": "^12.1.0",
"next-seo": "^4.28.1",
"npm-run-all": "^4.1.5",
"path": "^0.12.7",
"postcss": "8.4.6",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-import": "^14.1.0",
"postcss-loader": "^4.3.0",
"postcss-nested": "^5.0.6",
"postcss-preset-env": "^6.7.1",
"prettier": "^2.3.1",
"react-scripts": "^3.4.1",
"rollup": "^2.77.0",
"rollup-plugin-filesize": "^9.1.2",
"rollup-plugin-image": "^1.0.2",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-tailwindcss": "^1.0.0",
"sass-loader": "^12",
"tailwindcss": "^2.2.6",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-node-externals": "^3.0.0"
}
}
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const stylesHandler = MiniCssExtractPlugin.loader;
module.exports = {
devtool: "source-map",
context: __dirname,
entry: "./src/index.js",
externals: [nodeExternals({ importType: "umd" })],
output: {
filename: "[name].js",
path: path.resolve(__dirname, "./dist"),
libraryTarget: "umd",
library: {
name: "cruil",
type: "umd",
},
assetModuleFilename: (pathData) => {
const filepath = path.dirname(pathData.filename).split("/").slice(1).join("/");
return `${filepath}/[name].[hash][ext][query]`;
},
globalObject: "this",
},
experiments: {
outputModule: true,
},
optimization: {
runtimeChunk: "single",
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
options: {
encodeOptions: {
pngquant: {
quality: 90,
},
},
},
},
}),
],
splitChunks: {
chunks: "all",
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
// get the name. E.g. node_modules/packageName/not/this/part.js
// or node_modules/packageName
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
// npm package names are URL-safe, but some servers don't like # symbols
return `npm.${packageName.replace("#", "")}`;
},
},
},
},
},
module: {
rules: [
{
test: /\.js$|jsx/,
include: path.resolve(__dirname, "./src"),
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env", "#babel/preset-react"],
},
},
},
{
test: /\.(s(a|c)ss)$/,
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
include: path.resolve(__dirname, "./src"),
},
{
test: /\.css$/i,
use: [stylesHandler, "css-loader", "postcss-loader"],
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
include: path.resolve(__dirname, "./src/assets"),
type: "asset/resource",
},
],
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin(),
new webpack.DefinePlugin({
"process.env": {
// This has effect on the react lib size
NODE_ENV: JSON.stringify("production"),
},
}),
],
};
rollup.config.js
import babel from "#rollup/plugin-babel";
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import postcss from "rollup-plugin-postcss";
import filesize from "rollup-plugin-filesize";
import autoprefixer from "autoprefixer";
import image from "rollup-plugin-image";
import external from "rollup-plugin-peer-deps-external";
import replace from "rollup-plugin-replace";
import tailwind from "rollup-plugin-tailwindcss";
import pkg from "./package.json";
const INPUT_FILE_PATH = "src/index.js";
const OUTPUT_NAME = "main";
const GLOBALS = {
react: "React",
"react-dom": "ReactDOM",
"prop-types": "PropTypes",
};
const getBabelOptions = ({ useESModules }) => ({
babelrc: false,
exclude: "node_modules/**",
extensions: [".js", ".ts", ".jsx", ".tsx"],
babelHelpers: "runtime",
presets: [["#babel/preset-env", { modules: false }], "#babel/preset-react"],
plugins: [["#babel/transform-runtime", { regenerator: false, useESModules }], "#babel/plugin-syntax-jsx"],
});
const PLUGINS = [
external({
includeDependencies: true,
}),
image(),
tailwind({
input: "./src/styles/index.css",
purge: false,
}),
postcss({
extract: true,
modules: true,
plugins: [autoprefixer],
}),
resolve({
browser: true,
resolveOnly: [/^(?!react$)/, /^(?!react-dom$)/, /^(?!prop-types)/],
preferBuiltins: false,
}),
commonjs({
include: /node_modules/,
}),
replace({ "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV) }),
babel(getBabelOptions({ useESModules: true })),
filesize(),
];
const EXTERNAL = ["react", "react-dom", "prop-types"];
// https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
const CJS_AND_ES_EXTERNALS = EXTERNAL.concat(/#babel\/runtime/);
const OUTPUT_DATA = [
{
file: pkg.browser,
format: "umd",
},
{
file: pkg.main,
format: "cjs",
},
{
file: pkg.module,
format: "es",
},
];
const config = OUTPUT_DATA.map(({ file, format }) => ({
input: INPUT_FILE_PATH,
output: {
file,
format,
name: OUTPUT_NAME,
globals: GLOBALS,
},
external: ["cjs", "es"].includes(format) ? CJS_AND_ES_EXTERNALS : EXTERNAL,
plugins: PLUGINS,
}));
export default config;
postcss.config.js
module.exports = {
plugins: [
require("postcss-import"),
require("tailwindcss"),
require("postcss-flexbugs-fixes"),
require("postcss-nesting"),
require("postcss-custom-properties"),
require("autoprefixer"),
],
};
index.js
import "./styles/index.css";
import ExampleTestComponent from "./components/ExampleTestComponent";
...
export {
ExampleTestComponent,
...
}
ExampleTestComponent.js
import React from "react";
const ExampleTestComponent = (props) => {
return (
<div className="ExampleTestComponentClass">
--- This is a test ---
</div>
);
};
export default ExampleTestComponent;
index.css
#tailwind base;
#tailwind components;
#tailwind utilities;
Site Implementation
import ExampleTestComponent from "#github_account/package_name";
const HomePageTemplate = ({ heroItems, partners, newsItems, videos }) => {
const partnerItems = partners.map((partner) => ({
image: partner.logo,
url: partner.url,
}));
return (
<HomePageLayout heroItems={heroItems} partnerItems={partnerItems}>
<ExampleTestComponent />
<SuccessStoriesSlider videos={videos} />
<NewsBlock
newsItems={newsItems}
title="News"
subtitle="Latest news posts"
viewMoreBtnLabel="View Posts"
readMoreBtnLabel="Read More"
/>
</HomePageLayout>
);
};
export default HomePageTemplate;
UPDATE 1
Turns out a combination of using Yarn and adding the below
{
"resolutions": {
"postcss": "8"
}
}
to package.json, fixes the Postcss issue. So now I have the package created, I am attempting to import into the main site. However I'm now getting the error:
Error: Must use import to load ES Module: /node_modules/#github_account/package_name/node_modules/#babel/runtime/helpers/esm/defineProperty.js
require() of ES modules is not supported.
require() of /node_modules/#github_account/package_name/node_modules/#babel/runtime/helpers/esm/defineProperty.js from /node_modules/#github_account/package_name/build/main.cjs.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename defineProperty.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /node_modules/#github_account/package_name/node_modules/#babel/runtime/helpers/esm/package.json.
I keep getting a React minification warning when opening up my application.
I setup my webpack, package.json and redux store to settings that I thought would disable this warning, but it is still appearing.
Any help would be appreciated. I am copying over the code from my webpack, package.json and redux store. I am hosting my application on heroku.
Store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers/root_reducer';
const middlewares = [thunk];
if (process.env.NODE_ENV !== 'production') {
const logger = require('redux-logger');
middlewares.push(logger.createLogger());
}
const configureStore = (preloadedState = {}) => (
createStore(
rootReducer,
preloadedState,
applyMiddleware(...middlewares)
)
);
export default configureStore;
Webpack
var path = require('path');
var webpack = require("webpack");
var plugins = [];
var devPlugins = [];
var prodPlugins = [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: true
}
})
];
plugins = plugins.concat(
process.env.NODE_ENV === 'production' ? prodPlugins : devPlugins
)
module.exports = {
entry: './frontend/gym_bump.jsx',
output: {
path: path.resolve(__dirname, 'app', 'assets', 'javascripts'),
filename: './bundle.js',
},
module: {
loaders: [
{
test: [/\.jsx?$/],
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}
]
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '*']
}
};
package.json
"dependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"chart.js": "^2.6.0",
"jquery": "^3.2.1",
"moment": "^2.18.1",
"react": "^15.6.1",
"react-chartjs-2": "^2.6.1",
"react-dom": "^15.6.1",
"react-infinite-scroll-component": "^2.4.0",
"react-redux": "^5.0.6",
"react-router-dom": "^4.1.2",
"react-simple-charts": "0.0.19",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0",
"salad-ui": "^1.1.50",
"time-input": "^1.5.1",
"webpack": "^3.5.5",
"webpack-uglify-js-plugin": "^1.1.9"
},
"description": "This README would normally document whatever steps are necessary to get the application up and running.",
"version": "1.0.0",
"main": "index.js",
"directories": {
"doc": "docs",
"lib": "lib",
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"webpack": "webpack --watch",
"postinstall": "webpack"
},
"engines": {
"node": "8.2.1",
"npm": "5.3.0"
},
"devDependencies": {
"bundle-collapser": "^1.3.0",
"envify": "^4.1.0",
"uglify-js": "^3.0.28",
"uglify-js-brunch": "^2.10.0",
"uglifyify": "^4.0.3",
"redux-logger": "^3.0.6"
}
}
I fixed this, silly mistake. I was missing plugins: plugins, in my webpack.
module.exports = {
entry: './frontend/gym_bump.jsx',
output: {
path: path.resolve(__dirname, 'app', 'assets', 'javascripts'),
filename: './bundle.js',
},
**plugins: plugins,**
module: {
loaders: [
{
test: [/\.jsx?$/],
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}
]
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '*']
}
};
{
"name": "shopping-cart-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "karma start",
"start": "node server.js"
},
"author": "",
"license": "MIT",
"dependencies": {
"axios": "^0.9.1",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"body-parser": "^1.17.1",
"express": "^4.13.4",
"faker": "^4.1.0",
"marked": "^0.3.6",
"mongoose": "^4.9.6",
"nodemon": "^1.11.0",
"react": "^0.14.7",
"react-addons-test-utils": "^0.14.7",
"react-bootstrap": "^0.31.0",
"react-dom": "^0.14.7",
"react-router": "^2.0.0"
},
"devDependencies": {
"babel-core": "^6.5.1",
"babel-loader": "^6.2.2",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-preset-es2015": "^6.5.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"css-loader": "^0.23.1",
"expect": "^1.14.0",
"foundation-sites": "6.2.0",
"jquery": "^2.2.1",
"karma": "^0.13.22",
"karma-chrome-launcher": "^0.2.2",
"karma-mocha": "^0.2.2",
"karma-mocha-reporter": "^2.0.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.7.0",
"mocha": "^2.4.5",
"node-sass": "^3.4.2",
"sass-loader": "^3.1.2",
"script-loader": "^0.6.1",
"style-loader": "^0.13.0",
"webpack": "^1.12.13"
}
}
I am trying to implement server side routing for a react app i am working on. I am using react-router for this purpose. Here is part of my server.js code
const renderToString = require ('react-dom/server');
let match, RouterContext = require('react-router');
const routes = require ('/app/router');
const React = require('react');
app.get('*', (req, res) => {
match(
{ routes, location: req.url },
(err, redirectLocation, renderProps) => {
// in case of error display the error message
if (err) {
return res.status(500).send(err.message);
}
// in case of redirect propagate the redirect to the browser
if (redirectLocation) {
return res.redirect(302, redirectLocation.pathname + redirectLocation.search);
}
// generate the React markup for the current route
let markup;
if (renderProps) {
// if the current route matched we have renderProps
markup = renderToString(<RouterContext {...renderProps}/>);
} else {
// otherwise we can render a 404 page
markup = renderToString(<NotFoundPage/>);
res.status(404);
}
// render the index template with the embedded React markup
return res.render('index', { markup });
}
);
});
//my webpack config file
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: [
'script!jquery/dist/jquery.min.js',
'script!foundation-sites/dist/foundation.min.js',
'./app/app.jsx'
],
externals: {
jquery: 'jQuery'
},
plugins: [
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery'
})
],
output: {
path: __dirname,
filename: './public/bundle.js'
},
resolve: {
root: __dirname,
modulesDirectories: [
'node_modules',
'./app/components'
],
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0']
},
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/
}
]
},
sassLoader: {
includePaths: [
path.resolve(__dirname, './node_modules/foundation-sites/scss')
]
},
devtool: 'cheap-module-eval-source-map'
};
I get an unexpected token < at < RouterContext {...renderProps}/>.
I have looked over the tutorial am am working of off, but i am not so sure what i have done wrong. Any suggestion would be really appreciated
You are using the Babel presets react, es2015 and stage-0.
None of those presets includes the plugin you need to make the object spread syntax you are using work – this part of your code:
<RouterContext {...renderProps} />
You can fix your problem by adding the transform-object-rest-spread plugin to your Babel config like this:
module: {
loaders: [
{
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['transform-object-rest-spread']
},
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/
}
]
}
Don't forget to install the plugin using
npm install --save-dev babel-plugin-transform-object-rest-spread
I have been trying out React with Webpack and Redux and stumbled upon an
Uncaught SyntaxError: Unexpected token import.
I know that there is a lot of questions like these, but I have find none that involves Redux.
Here is my webpack config:
var app_root = 'src'; // the app root folder: src, src_users, etc
var path = require('path');
var CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
app_root: app_root, // the app root folder, needed by the other webpack
configs
entry: [
// http://gaearon.github.io/react-hot-loader/getstarted/
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'babel-polyfill',
__dirname + '/' + app_root + '/index.js',
],
output: {
path: __dirname + '/public/js',
publicPath: 'js/',
filename: 'bundle.js',
},
module: {
loaders: [
{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
exclude: /node_modules/,
},
{
// https://github.com/jtangelder/sass-loader
test: /\.scss$/,
loaders: ['style', 'css', 'sass'],
},
{
test: /\.css$/,
loaders: ['style', 'css'],
}
],
},
devServer: {
contentBase: __dirname + '/public',
},
plugins: [
new CleanWebpackPlugin(['css/main.css', 'js/bundle.js'], {
root: __dirname + '/public',
verbose: true,
dry: false, // true for simulation
}),
],
};
index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore} from 'redux';
// importera App komponenten
import App from './components/App';
// importera stylesheet
import './stylesheets/main.scss';
//importera reducer
import { reducers } from './reducers/index';
import Provider from "react-redux/src/components/Provider";
// skapa users-list, tomt objekt
let users = [];
for (let i = 1; i < 10; i++) {
// fyller objektet med användare med dessa villkor
users.push({
id: i,
username: 'Andreas' + i,
job: 'leethacker' + i,
});
const initialState = {
users: users,
}
}
// skapa Store
const store = createStore(reducers, initialState);
// skriver sedan ut denna komponent, render är Reacts funktion för att
skriva ut
ReactDOM.render(
<Provider store ={store}>
<App/>
</Provider> , document.getElementById('App'));
Package.json file:
{
"name": "redux-minimal",
"version": "1.0.0",
"description": "Start building complex react-redux apps today, with
this minimalist easy to understand starter kit (boilerplate)",
"keywords": [
"react",
"redux",
"minimal",
"starter kit",
"boilerplate"
],
"main": "index.js",
"homepage": "http://redux-minimal.js.org/",
"repository": {
"type": "git",
"url": "https://github.com/catalin-luntraru/redux-minimal"
},
"scripts": {
"start": "webpack-dev-server --inline --hot --history-api-fallback --
host localhost --port 8080",
"build-dev": "webpack --config webpack.dev.config.js",
"build-prod": "webpack -p --config webpack.prod.config.js",
"test": "mocha --recursive --compilers js:babel-register --require
babel-polyfill --require ignore-styles",
"test-watch": "npm test -- --watch"
},
"babel": {
"presets": [
"es2015",
"react",
"stage-3"
]
},
"author": "Catalin Luntraru",
"license": "MIT",
"dependencies": {
"react": "^15.4.2",
"react-bootstrap": "^0.30.7",
"react-dom": "^15.4.2",
"react-redux": "^5.0.2",
"react-router": "^3.0.1",
"react-router-bootstrap": "^0.23.1",
"react-router-redux": "^4.0.7",
"redux": "^3.6.0",
"redux-form": "^6.4.3",
"redux-saga": "^0.14.3"
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-polyfill": "^6.20.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-3": "^6.17.0",
"babel-runtime": "^6.20.0",
"clean-webpack-plugin": "^0.1.15",
"css-loader": "^0.26.1",
"enzyme": "^2.7.0",
"extract-text-webpack-plugin": "^1.0.1",
"ignore-styles": "^5.0.1",
"mocha": "^3.2.0",
"node-sass": "^4.3.0",
"react-addons-test-utils": "^15.4.2",
"react-hot-loader": "^1.3.1",
"redux-freeze": "^0.1.5",
"sass-loader": "^4.1.1",
"style-loader": "^0.13.1",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2",
"whatwg-fetch": "^2.0.1"
}
}
The error line that I see is indicative of a error that is not being transpiled correct by babel.
See this please,
"unexpected token import" in Nodejs5 and babel?
Also, please add the index.js entry file, package.json to be more informative.
Hope this helps!
The error is in webpack.config.js ,as the babel loader is not included properly in config file.change your code as :
module: {
loaders: [
{ test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['react', 'es2015']
}
},
I am facing issue due to large webpack bundle size.
The size of my bundle size is nearby 166 kb. I am running webpack with -p flag. Most of the size is due to bundling of react module in my bundle file. So, what I am trying to do is that I am making two bundles: one which contain my app specific code and the other one which contains minified version of the npm which do not change frequently.
My bundle size is now 20 Kb.
Here is my webpack config file :
var path = require('path');
var webpack = require("webpack");
var node_modules_dir = path.resolve(__dirname, 'node_modules');
var config = {
entry: path.resolve(__dirname, 'index.js'),
output: getOutput(),
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
],
devtool: process.env.NODE_ENV === 'production' ? false : "eval",
module: {
loaders: [
{
test: /\.scss$/,
include: /src/,
loaders: [
'style',
'css',
'autoprefixer?browsers=last 3 versions',
'sass?outputStyle=expanded'
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'url?limit=8192',
'img'
]
},
{
test: /\.jsx?$/,
exclude: (node_modules_dir),
loaders: [
'react-hot',
'babel-loader?presets[]=stage-0,presets[]=react,presets[]=es2015',
]
}, {
test: /\.css$/,
loader: 'style-loader!css-loader'
}
]
}
};
module.exports = config;
function getOutput() {
if (process.env.NODE_ENV === 'production') {
return {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
} else {
return {
publicPath: 'http://localhost:3000/',
filename: 'dist/bundle.js'
}
}
}
and here is my code :
import {connect, Provider} from 'react-redux';
import React from "react"
import {createStore, combineReducers} from 'redux';
import reducers from "./reducers";
import {increment} from "./actions/App.js";
var store = createStore(
combineReducers({
...reducers
})
);
class App extends React.Component {
render() {
return <div>
<span>Value is : {this.props.value}</span>
<div onClick={this.props.increment}><span>Increment</span></div>
</div>
}
}
App = connect((state)=> {
return {value: state.app.value}
}, {increment})(App);
module.exports = React.createClass({
render: ()=> {
return <Provider store={store}><App /></Provider>
}
});
and here is my package.json file
{
"name": "Sample App",
"version": "0.0.1",
"private": true,
"scripts": {
"webpack-server": "webpack-dev-server --hot --progress --colors --port 3000",
"serve-web": "npm run webpack-server",
"deploy": "NODE_ENV=production webpack -p --optimize-minimize"
},
"dependencies": {
"babel-core": "6.9.0",
"babel-loader": "6.2.4",
"babel-plugin-transform-runtime": "6.9.0",
"babel-preset-es2015": "6.9.0",
"babel-preset-react": "6.5.0",
"babel-preset-stage-0": "6.5.0",
"babel-relay-plugin": "^0.9.1",
"babel-runtime": "6.9.0",
"css-loader": "^0.23.0",
"file-loader": "^0.8.5",
"http-server": "^0.8.0",
"img-loader": "^1.3.1",
"node-fetch": "^1.5.3",
"postcss-loader": "^0.8.0",
"react": "15.3.2",
"react-dom": "^15.1.0",
"react-hot-loader": "^1.2.8",
"react-redux": "^4.4.5",
"redux": "^3.6.0",
"source-map-loader": "^0.1.5",
"url-loader": "^0.5.7",
"webpack": "1.13.1",
"webpack-dev-server": "1.14.1"
},
"jest": {
"preset": "jest-react-native"
},
"devDependencies": {
"babel-cli": "6.9.0",
"babel-core": "^6.9.0",
"babel-loader": "^6.2.4"
},
"engines": {
"npm": ">=3"
}
}
So, I have changed
module.exports = require('./lib/React');
to
module.exports = window.React;
in react.js file of react module as other npm like redux is also using react npm.
Is it a good thing to apply this patch in react.js file of react npm?
Is it a good thing to make two bundles like this?
You can use source map explorer to detect what is the problem.
https://www.npmjs.com/package/source-map-explorer