I updated my Nextjs website to React18 and wanted to switch to SWC compiler. I am having a hard time wrapping my head around how to get this to work. I didn't have a custom babelrc config before. Whatever I do I keep getting
Error occurred prerendering page "/en/auth". Read more: https://nextjs.org/docs/messages/prerender-error
ReferenceError: React is not defined
When building my site
This is my next.config.js
const {
PHASE_DEVELOPMENT_SERVER,
PHASE_PRODUCTION_BUILD,
} = require("next/constants");
const { i18n } = require("./next-i18next.config");
module.exports = (phase) => {
/**
* #type {import('next').NextConfig}
*/
const nextConfig = {
env,
swcMinify: false,
//TODO
/* reactStrictMode: true, */
i18n,
//TODO
eslint: {
ignoreDuringBuilds: true,
},
compiler: {
removeConsole: isProd ? { exclude: ["error"] } : true,
},
experimental: {
forceSwcTransforms: true,
},
webpack: (config, options) => {
config.module.rules.push({
test: /\.pdf$/,
issuer: /\.tsx?$/,
use: [
"next-swc-loader",
{
loader: "swc-loader",
options: {
babel: false,
name: "*.pdf",
},
},
],
});
config.module.rules.push({
test: /\.svg$/,
issuer: /\.tsx?$/,
include: [options.dir],
use: [
"next-swc-loader",
{
loader: "#svgr/webpack",
options: { babel: false },
},
],
});
return config;
},
};
return nextConfig;
};
In babel you can set the runtime to fix this
{
"presets": [
"#babel/preset-env",
["#babel/preset-react", {"runtime": "automatic"}]
]
}
Is there similar setup for SWC? From their docs it seems that this should be handled out of the box so my only idea is that SWC is not actually being used but its still defaulting to Babel
EDIT:
My package.json
{
"name": "#example/site",
"private": true,
"version": "1.0.0",
"scripts": {
"dev": "next dev -p 3005",
"build": "next build",
"start": "next start",
"svgr": "npx #svgr/cli -d src/components/icons --ignore-existing --icon --typescript public/icons",
"prepare-husky": "husky install",
"format": "prettier -w .",
"format:check": "prettier -c .",
"lint": "next lint",
"lint:fix": "eslint src --fix && yarn format",
"lint:strict": "eslint --max-warnings=0 src"
},
"dependencies": {
"#hookform/resolvers": "2.9.7",
"#svgr/webpack": "6.3.1",
"axios": "0.27.2",
"clsx": "1.2.1",
"firebase": "9.9.2",
"framer-motion": "7.5.0",
"immer": "9.0.15",
"lottie-react": "2.3.1",
"next": "12.3.1",
"next-i18next": "10.2.0",
"next-language-detector": "1.0.2",
"prettier": "2.7.1",
"react": "18.2.0",
"react-color": "2.19.3",
"react-date-picker": "8.4.0",
"react-datepicker": "4.8.0",
"react-dom": "18.2.0",
"react-dropzone": "12.1.0",
"react-hook-form": "7.36.1",
"react-icons": "4.4.0",
"react-lottie-player": "1.4.3",
"react-phone-number-input": "3.2.6",
"react-query": "3.39.2",
"react-responsive": "9.0.0-beta.10",
"react-tippy": "1.4.0",
"react-use": "17.4.0",
"tailwind-merge": "1.5.1",
"tailwind-scrollbar-hide": "1.1.7",
"yup": "0.32.11",
"zustand": "3.7.0"
},
"devDependencies": {
"#svgr/cli": "6.3.1",
"#swc/core": "^1.3.4",
"#types/node": "17.0.15",
"#types/react": "18.0.17",
"#types/react-color": "3.0.6",
"#types/react-datepicker": "4.4.2",
"#types/react-dom": "18.0.6",
"autoprefixer": "10.4.8",
"config": "workspace:*",
"dotenv": "16.0.1",
"eslint": "8.21.0",
"install": "0.13.0",
"npm": "8.16.0",
"postcss": "8.4.16",
"swc-loader": "^0.2.3",
"tailwindcss": "3.1.8",
"tsconfig": "workspace:*",
"typescript": "4.7.4"
}
}
Swc compilar is for nextjs it is good that you updated React to version 18.xx but you will have to update next js to version 12. 12.3 for swc minify. We don't have to do any settings in next config file. Swc is automatically used at build.
Related
I recently joined a company that works with react (classes) and typescript, I was flabbergasted when I knew that the react they are using does not hot/live reload on changes (CSS, state, or any change), what happens on changes is webpack recompiles (takes around 25 seconds) and to see changes I should reload the page which is slowing down the development experience greatly.
Talking to the manager it was decided that we do a migration to a new create react app gradually as there is lots of code and redundancy and we want to use functional react hooks (which will take years maybe as the app is big) but until then I want to resolve the hot reload issue.
I believe the react app a long time ago was not started with creat-react-app or something.
Just to mention I have 1.5 yrs experience in the industry so config stuff is still new to me and am just doing this for my learning benefits and to improve the team experience, it's not really an assigned task to do.
Below are our package.json, webpack file, and index file. Please let me know if you need to see anything else.
Package.json:
{
"name": "web-front-end",
"version": "1.22.19",
"description": "HTML5 implementation of the <our company name>. Written in Typescript, compiled to JavaScript, bundled with Webpack, executing on NodeJS, using React, adopting FLUX patterns.",
"private": true,
"scripts": {
"babel": "babel built/client/js/client.js -o built/client/js/client.js",
"clean": "rm -rf node_modules && rm -rf built && rm -rf coverage && echo 'clean complete'",
"reset": "yarn clean && yarn cache clean && yarn install --frozen-lockfile",
"compile": "yarn compile-client && yarn compile-server && yarn babel",
"debug-client": "NODE_ENV=debug webpack --config webpack.dev.js && echo 'client compile complete'",
"compile-client": "NODE_ENV=production webpack --config webpack.prod.js && echo 'production client compile complete'",
"compile-client-dev": "NODE_ENV=development webpack --config webpack.dev.js && echo 'development client compile complete'",
"compile-client-dev-watch": "NODE_ENV=development webpack --config webpack.dev-watch.js",
"compile-server": "tsc -p src/server && echo 'server compile complete'",
"compile-client-watch": "NODE_ENV=development webpack --config webpack.dev-watch.js",
"compile-server-watch": "tsc -p src/server --watch",
"validate": "yarn --ignore-engines && tslint './src/**/*.{ts,tsx}' './test/**/*.{ts,tsx}' && echo 'validate complete'",
"start-server": "node ./built/server/ServerApp.js",
"test": "tslint --project test && tslint --project src/app && tsc -p test --jsx react && node ./node_modules/jest/bin/jest.js --config=jest.test.config.json --coverage --verbose",
"lint-fix": "tslint --fix --project src && tslint --fix --project test",
"prepare": "patch-package"
},
"dependencies": {
"#emotion/react": "^11.9.3",
"#emotion/styled": "^11.9.3",
"#mui/icons-material": "^5.8.4",
"#mui/material": "^5.8.4",
"#mui/styles": "^5.8.4",
"#stripe/stripe-js": "1.11.0",
"assert": "^2.0.0",
"axios": "^0.27.2",
"blob-stream": "0.1.3",
"buffer": "^6.0.3",
"compression": "1.7.3",
"compression-webpack-plugin": "^10.0.0",
"connected-react-router": "^6.9.2",
"cors": "2.8.4",
"device-uuid": "1.0.4",
"dotenv": "6.0.0",
"express": "4.16.3",
"file-saver": "^2.0.5",
"html-to-image": "^1.10.8",
"https-browserify": "^1.0.0",
"js-cookie": "2.2.0",
"node-zip": "1.1.1",
"path-to-regexp": "2.4.0",
"pug": "2.0.3",
"query-string": "6.1.0",
"react": "17.0.0",
"react-copy-to-clipboard": "5.0.1",
"react-dom": "^17.0.2",
"react-form-validator-core": "0.4.4",
"react-hook-form": "^7.36.0",
"react-inlinesvg": "2.3.0",
"react-jss": "8.5.1",
"react-lazy-load": "3.0.13",
"react-markdown": "4.0.4",
"react-material-ui-form-validator": "^3.0.1",
"react-player": "1.14.2",
"react-redux": "^7.2.6",
"react-router": "5.2.1",
"react-router-dom": "5.3.0",
"react-share": "2.4.0",
"react-speech-recognition": "^3.10.0",
"react-stripe-elements": "2.0.1",
"react-svgmt": "^1.2.0",
"react-virtualized": "9.22.3",
"react-youtube": "7.9.0",
"recompose": "0.27.1",
"rect": "1.2.1",
"redux": "4.0.0",
"redux-thunk": "2.3.0",
"regenerator-runtime": "^0.13.9",
"shortid": "2.2.15",
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"svg-to-pdfkit": "0.1.7",
"url": "^0.11.0",
"utf8": "3.0.0"
},
"devDependencies": {
"#babel/cli": "^7.17.6",
"#babel/core": "^7.17.8",
"#babel/types": "^7.17.0",
"#types/blob-stream": "0.1.29",
"#types/code": "4.0.4",
"#types/detect-browser": "3.0.0",
"#types/jest": "25.2.3",
"#types/js-cookie": "2.2.1",
"#types/lab": "11.1.0",
"#types/react": "17.0.14",
"#types/react-dom": "17.0.14",
"#types/react-inlinesvg": "1.0.0",
"#types/react-redux": "^7.1.20",
"#types/react-router": "4.4.5",
"#types/react-virtualized": "9.21.18",
"#types/shortid": "0.0.29",
"#types/utf8": "2.1.6",
"awesome-typescript-loader": "3.4.1",
"copy-webpack-plugin": "4.5.1",
"detect-browser": "3.0.1",
"fork-ts-checker-webpack-plugin": "^7.2.13",
"jest": "^27.5.1",
"patch-package": "6.1.2",
"postinstall-postinstall": "2.0.0",
"process": "^0.11.10",
"source-map-loader": "0.2.3",
"source-map-support": "0.4.18",
"ts-jest": "27.1.2",
"ts-loader": "^9.3.1",
"ts-mockito": "2.3.0",
"ts-node": "^10.8.1",
"tslint": "^6.0.1",
"tslint-eslint-rules": "5.4.0",
"tslint-react": "^5.0.0",
"typescript": "4.1.5",
"webpack": "^5.73.0",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^4.10.0",
"webpack-merge": "^5.8.0"
},
"resolutions": {
"#types/prop-types": "15.7.5",
"#types/unist": "2.0.0",
"#types/react-transition-group": "2.0.8",
"#types/react": "17.0.14",
"#types/react-dom": "17.0.14"
},
"repository": {
"type": "git",
"url": "our repo link"
},
"author": "our company name",
"license": "MIT",
}
Webpack.common.js:
const path = require("path");
const webpack = require('webpack');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
entry: "./src/app/Main.ts",
cache: false,
optimization: {
providedExports: true,
usedExports: true,
removeAvailableModules: true,
removeEmptyChunks: true,
mergeDuplicateChunks: true,
chunkIds: 'named',
},
plugins: [
new webpack.ProvidePlugin({process: "process/browser"}),
new ForkTsCheckerWebpackPlugin(
{
typescript: {
configFile: './src/app/tsconfig.json'
}
}),
],
module: {
rules: [
{
test: /\.tsx?$/i,
loader: "ts-loader",
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
generator: {
filename: 'assets/[hash][ext]',
},
},
],
},
resolve: {
alias: {
core: path.join(__dirname, "src", "core"),
client: path.join(__dirname, "src", "client"),
server: path.join(__dirname, "src", "server"),
'<our company name>-typescript-common': path.resolve(__dirname, 'node_modules/<our company name>-typescript-common/'),
},
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js", ".jsx"],
fallback: {
"util": require.resolve('util'),
"os": false,
"fs": false,
"path": false,
"zlib": false,
"buffer": require.resolve('buffer'),
"http": require.resolve('stream-http'),
"https": require.resolve('https-browserify'),
"url": require.resolve('url'),
"stream": require.resolve('stream-browserify'),
},
},
output: {
path: path.resolve(__dirname, "built"),
filename: "client/js/client.js",
clean: true,
},
};
index.js (called Main.ts on our codebase)
import { render } from 'react-dom';
import { AppWrapper } from './view/App/AppWrapper';
declare var window: any;
class CompanyName {
constructor() {
window.dataLayer = window.dataLayer || [];
window._hsq = window._hsq || [];
const rootHtmlElement = document.body.appendChild(document.createElement('div'));
render(new AppWrapper({
lang: window.appConfig.LANGUAGE,
appConfig: window.appConfig,
startupTimestamp: window.sts}).render(), rootHtmlElement);
}
}
// tslint:disable-next-line:no-unused-expression
new CompanyName();
webpack.dev-watch.js:
const { merge } = require("webpack-merge");
const common = require("./webpack.dev.js");
const path = require('path');
module.exports = merge(common, {
watch: true,
optimization: {
minimize: false,
mangleExports: false,
mangleWasmImports: false
},
watchOptions: {
ignored: [
path.posix.resolve(__dirname, './node_modules'),
path.posix.resolve(__dirname, './rfg'),
path.posix.resolve(__dirname, './patches'),
path.posix.resolve(__dirname, './built'),
],
poll: 1500,
aggregateTimeout: 1000,
},
});
I would be grateful if you provide any explanations, explanatory links or videos in your answers so I can learn more.
Thanks.
I am trying to build a component library for myself with a few overrides. But it's constantly giving me an insane challenge. I can't import it into my projects. Rollup for some reason is packing the whole react lib into my bundle.js file.
This rollup config
/* eslint-disable */
import { readdirSync } from 'fs';
import path from 'path';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import replace from 'rollup-plugin-replace';
import resolve from 'rollup-plugin-node-resolve';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';
import pkg from './package.json';
const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.json'];
const CODES = [
'THIS_IS_UNDEFINED',
'MISSING_GLOBAL_NAME',
'CIRCULAR_DEPENDENCY'
];
const discardWarning = (warning) => {
if (CODES.includes(warning.code)) {
return;
}
console.error(warning);
};
const env = process.env.NODE_ENV;
const commonPlugins = () => [
postcss({
extract: true,
modules: true,
use: ['sass']
}),
external(),
babel({
babelrc: false,
presets: [['#babel/preset-env', { modules: false }], '#babel/preset-react'],
extensions: EXTENSIONS,
exclude: [
'node_modules/**',
'src/*/*.stories.js',
'src/*/*.spec.js',
'src/*/*.test.js'
]
}),
commonjs({
include: /node_modules/
}),
replace({ 'process.env.NODE_ENV': JSON.stringify(env) }),
resolve()
];
export default [
{
onwarn: discardWarning,
input: 'src/index.js',
output: {
esModule: false,
file: pkg.unpkg,
format: 'cjs',
name: 'ph-shared',
exports: 'named'
globals: {
antd: 'antd',
react: 'React',
'react-dom': 'ReactDOM'
}
},
external: ['react', '#ant-design', 'react-notification-system', 'antd'],
plugins: [...commonPlugins(), env === 'production' && terser()],
output: [{ dir: 'dist', format: 'cjs', exports: 'named', sourcemap: true }]
}
];
and this is package.json file
{
"name": "ph-shared",
"version": "0.0.1",
"author": "usmantahirr",
"description": "Component library for PH",
"main": "src/index.js",
"source": "src/index.js",
"module": "dist/bundle.js",
"engines": {
"node": ">=12"
},
"scripts": {
"build": "rollup -c",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint ./src/",
"lint:fix": "eslint ./src/ --fix",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,css}": [
"prettier --write",
"npm run lint:fix",
"git add"
]
},
"peerDependencies": {
"#ant-design/icons": "^4.2.2",
"react-notification-system": "^0.4.0",
"antd": "^4.6.4",
"react": "^16.13.1",
"node-sass": "^4.14.1"
},
"devDependencies": {
"#ant-design/icons": "^4.2.2",
"#babel/core": "^7.11.6",
"#babel/preset-env": "^7.11.5",
"#babel/preset-react": "^7.10.4",
"#storybook/addon-actions": "^6.0.21",
"#storybook/addon-essentials": "^6.0.21",
"#storybook/addon-knobs": "^6.0.21",
"#storybook/addon-links": "^6.0.21",
"#storybook/preset-create-react-app": "^3.1.4",
"#storybook/react": "^6.0.21",
"antd": "^4.6.4",
"babel": "^6.23.0",
"babel-loader": "^8.1.0",
"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",
"husky": "^1.3.1",
"lint-staged": "^8.1.5",
"node-sass": "^4.14.1",
"prettier": "^2.0.4",
"react-is": "^16.13.1",
"react-notification-system": "^0.4.0",
"react-scripts": "^3.4.3",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-peer-deps-external": "^2.2.3",
"rollup-plugin-postcss": "^3.1.8",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-terser": "^7.0.2",
"sass-resources-loader": "^2.1.0",
"styled-components": "^5.2.0"
},
"dependencies": {}
}
I also want to override some antD styles using SCSS. and it's converting all the classes with funny names even though they are not scss modules. It's extracting out a single file with all of my classes renamed. I was expecting only scss modules classes to be renamed.
I used the instructions from the official react documentation, but localhost still starts from http://.
My package.json file where I tried to add a solution.
I also tried 'set HTTPS = true && npm start'.
{
"name": "project",
"version": "1.0.0",
"description": "Project",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack -p",
"start": "webpack-dev-server --hot --inline -d && HTTPS=true react-scripts start",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"#babel/polyfill": "^7.8.7",
"formik": "^2.1.4",
"ramda": "^0.27.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-https-redirect": "^1.1.0",
"react-iframe": "^1.8.0",
"react-router-dom": "^5.0.1",
"react-scripts": "^3.4.1",
"react-scroll-up-button": "^1.6.4",
"styled-components": "^5.0.1",
"whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"#babel/core": "^7.7.5",
"#babel/plugin-proposal-async-generator-functions": "^7.8.3",
"#babel/plugin-proposal-class-properties": "^7.7.4",
"#babel/plugin-transform-async-to-generator": "^7.8.3",
"#babel/plugin-transform-regenerator": "^7.8.7",
"#babel/preset-env": "^7.7.6",
"#babel/preset-react": "^7.7.4",
"autoprefixer": "^9.6.1",
"babel-loader": "^8.0.6",
"css-loader": "^3.2.0",
"file-loader": "^4.2.0",
"gh-pages": "^2.2.0",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.12.0",
"postcss-loader": "^3.0.0",
"react-inlinesvg": "^1.2.0",
"sass-loader": "^7.2.0",
"style-loader": "^1.0.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
}
}
webpackconfig.js
const path = require("path");
const Html = require('html-webpack-plugin');
module.exports = {
entry: [
"whatwg-fetch",
"./js/index.js",
],
output: {
filename: "js/out.js",
path: path.resolve(__dirname, "build")
},
devServer: {
port: 3001,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
}
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: "postcss-loader",
options: {
plugins: () => [
require("autoprefixer")()
],
},
},
'sass-loader',
]
},
{
test: /\.(jpg|jpeg|gif|png)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
publicPath: 'images',
outputPath: 'images',
}
}
},
{
test: /\.(eot|ttf|woff|woff2)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
publicPath: 'fonts',
outputPath: 'fonts',
}
}
},
]
},
plugins: [
new Html({
filename: 'index.html',
template: './index.html',
})
]
};
I'm a beginner and I can't deal with it, if someone can help me, I will be very grateful.
The options for SET HTTPS=true are for projects that are made with create-react-app. Since you have a webpack configuration file of your own, you have to change the configuration for enabling HTTPS.
You can do this with:
devServer: {
https: true
}
This enables a self signed certificate. You can provide a certifiate with:
devServer: {
https: true,
key: fs.readFileSync('/path/to/server.key'),
cert: fs.readFileSync('/path/to/server.crt'),
ca: fs.readFileSync('/path/to/ca.pem'),
}
Docs
In package.json try add set HTTPS=true instead of HTTPS=true in start script.
I'm trying to make my tests in Typescript with Jest and Enzyme but the tests throws a SyntaxError:
FAIL src/_components/Button/__tests__/Button.spec.tsx
● Test suite failed to run
/Users/mikaelboutin/Desktop/self/gatsby-react-intl-starter/jest.setup.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Enzyme, { mount, render, shallow } from 'enzyme'
^^^^^^
SyntaxError: Unexpected identifier
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:537:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:579:25)
I tried to include ts-jest. It won't solve the problem. I changed many times the jest.config.js with some advices of many articles. I set a jest.preprocess.js` to pass babel presets to it.
I followed https://github.com/facebook/jest/issues/6229 but nothing do it on my project.
My repo is here: https://github.com/DWboutin/gatsby-intl-redux-typescript
jest.config.js
module.exports = {
preset: 'ts-jest',
transform: {
'^.+\\.(ts|tsx)?$': `<rootDir>/jest-preprocess.js`
},
moduleNameMapper: {
'.+\\.(css|styl|less|sass|scss)$': `identity-obj-proxy`,
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': `<rootDir>/__mocks__/file-mock.js`
},
testPathIgnorePatterns: [`node_modules`, `.cache`, `dist`],
transformIgnorePatterns: [`node_modules/(?!(gatsby)/)`],
globals: {
__PATH_PREFIX__: ``
},
testURL: `http://localhost`,
setupFiles: [`<rootDir>/jest.setup.js`, `<rootDir>/loadershim.js`],
snapshotSerializers: ['enzyme-to-json/serializer']
}
jest.setup.js
import Enzyme, { mount, render, shallow } from 'enzyme'
import * as Adapter from 'enzyme-adapter-react-16'
// React 16 Enzyme adapter
Enzyme.configure({ adapter: new Adapter() })
// Make Enzyme functions available in all test files without importing
global.shallow = shallow
global.render = render
global.mount = mount
jest.preprocess.js
const babelOptions = {
presets: [
[
'#babel/preset-typescript',
{
isTSX: true,
allExtensions: true
}
],
'babel-preset-gatsby'
]
}
module.exports = require('babel-jest').createTransformer(babelOptions)
loadershim.js
global.___loader = {
enqueue: jest.fn(),
}
.babelrc
{
"presets": [
[
"#babel/preset-typescript",
{
"isTSX": true,
"allExtensions": true
}
],
"babel-preset-gatsby"
]
}
src/_components/Button/tests/Button.spec.tsx (my only test for now)
import { shallow } from 'enzyme'
import React from 'react'
import Button from '../'
describe('Button', () => {
describe('Primary', () => {
it('should match snapshot', () => {
const wrapper = shallow(<Button>Test</Button>)
expect(wrapper).toMatchSnapshot()
})
})
})
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "esnext",
"jsx": "preserve",
"lib": ["dom", "es2015", "es2017"],
"strict": true,
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"skipLibCheck": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": false,
"preserveConstEnums": true
},
"include": ["./src/**/*"],
"exclude": ["node_modules", "public", ".cache"]
}
package.json
{
"name": "gatsby-starter-default",
"description": "Gatsby default starter",
"version": "1.0.0",
"author": "Mikael Boutin <mikaelboutin.dw#gmail.com>",
"dependencies": {
"#reach/router": "^1.2.1",
"#types/styled-components": "^4.1.19",
"classnames": "^2.2.6",
"gatsby": "^2.15.18",
"gatsby-image": "^2.2.19",
"gatsby-plugin-manifest": "^2.2.17",
"gatsby-plugin-offline": "^3.0.7",
"gatsby-plugin-react-helmet": "^3.1.7",
"gatsby-plugin-sharp": "^2.2.24",
"gatsby-plugin-typescript": "^2.1.8",
"gatsby-source-filesystem": "^2.1.24",
"gatsby-transformer-sharp": "^2.2.15",
"omit.js": "^1.0.2",
"prop-types": "^15.7.2",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-helmet": "^5.2.1",
"react-intl": "^3.2.4",
"react-redux": "^7.1.1",
"redux": "^4.0.4",
"styled-components": "^4.4.0",
"typescript": "^3.6.3"
},
"keywords": [
"gatsby"
],
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"start": "npm run develop",
"format": "npm run format:src && npm run format:root",
"format:src": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
"format:root": "prettier --write \"./*.js\"",
"transpile": "npm run build && babel src/_components/ --extensions \".ts,.tsx\" --ignore \"**/__tests__/**\" -d dist",
"clean": "rm -rf .cache public dist",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:update": "jest --updateSnapshot"
},
"devDependencies": {
"#babel/cli": "^7.6.0",
"#babel/preset-typescript": "^7.6.0",
"#types/enzyme": "^3.10.3",
"#types/enzyme-adapter-react-16": "^1.0.5",
"#types/jest": "^24.0.18",
"#types/mocha": "^5.2.7",
"#types/node": "^12.7.5",
"#types/react": "^16.9.2",
"#types/react-dom": "^16.9.0",
"#types/react-helmet": "^5.0.10",
"babel-jest": "^24.9.0",
"babel-preset-gatsby": "^0.2.14",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.4.0",
"husky": "^3.0.5",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.9.0",
"prettier": "^1.18.2",
"react-test-renderer": "^16.9.0",
"redux-devtools-extension": "^2.13.8",
"source-map-support": "^0.5.13",
"ts-jest": "^24.1.0",
"ts-node": "^8.4.1"
},
"repository": {
"type": "git",
"url": "https://github.com/DWboutin/gatsby-react-intl-starter"
},
"husky": {
"hooks": {
"pre-commit": "npm run transpile"
}
}
}
I expected the tests to run correctly, but it throws a SyntaxError: Unexpected identifier on Enzyme.
Thank you for your help!
From your jest.config.js you are not parsing .js files (jest.setup.js where the error comes from)
Modifying this line :
transform: {
'^.+\\.(ts|tsx)?$': `<rootDir>/jest-preprocess.js`
},
to add .js extensions like so:
transform: {
'^.+\\.(ts|tsx|js)?$': `<rootDir>/jest-preprocess.js`
},
Should do the trick.
Also, importing Adapter like this will throw an error
import * as Adapter from 'enzyme-adapter-react-16'
use this instead
import Adapter from 'enzyme-adapter-react-16'
I have recently updated my react-native-web project to use a more recent react native version to use a more recent expo version.
with the help of npm I have now a fully functional updated code running on ios and android.
However I have still difficulties running it on webpack with different problems related (to the best of my understanding) to a webpack that needs to be updated as well to a higher version (2 -> 3or4).
in this process I have found difficulties matching the right webpack version to the right dev-server and cli.
here is my package.json
"devDependencies": {
"babel-loader": "^7.1.2",
"babel-plugin-expo-web": "^0.0.5",
"babel-plugin-react-native-web": "0.9.9",
"babel-plugin-transform-decorators-legacy": "1.3.4",
"babel-plugin-transform-imports": "1.4.1",
"babel-plugin-transform-runtime": "6.23.0",
"css-loader": "0.28.7",
"docz": "^0.12.16",
"eslint-plugin-react": "^7.10.0",
"file-loader": "^1.1.7",
"gh-pages": "^1.2.0",
"jest-expo": "^30.0.0",
"react-native-scripts": "^2.0.1",
"react-styleguidist": "^8.0.6",
"react-test-renderer": "16.4.1",
"style-loader": "^0.19.0",
"sw-precache-webpack-plugin": "^0.11.5",
"webpack-cli": "^3.1.2",
"webpack-manifest-plugin": "^2.0.4"
},
"main": "./node_modules/react-native-scripts/build/bin/crna-entry-web.js",
"scripts": {
"start": "expo start",
"eject": "react-native-scripts eject",
"android": "react-native-scripts android",
"ios": "react-native-scripts ios",
"test": "jest",
"clean": "rm -rf node_modules && yarn cache clean && npm cache clean --force",
"make": "yarn",
"docu:dev": "docz dev",
"docu:build": "docz build",
"web": "webpack-dev-server -d --config ./webpack.config.js --env dev --inline --hot --colors --content-base app/ --history-api-fallback",
"build:dev": "NODE_ENV=production webpack --env dev --config ./webpack.config.js",
"build:prod": "NODE_ENV=production webpack --env prod --config ./webpack.config.js"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"#sentry/browser": "^4.4.1",
"#sentry/cli": "^1.31.0",
"audit": "0.0.6",
"babel-plugin-transform-remove-console": "^6.9.4",
"es6-symbol": "^3.1.1",
"expo": "^30.0.0",
"expo-analytics": "1.0.7",
"expo-firebase-crashlytics": "1.0.0",
"expo-web": "0.0.14",
"firebase": "^5.0.4",
"jsc-android": "^224109.1.0",
"mobx": "4",
"mobx-react": "5.1.0",
"npm": "^6.5.0",
"prop-types": "^15.6.2",
"query-string": "^6.2.0",
"react": "16.5.1",
"react-art": "16.5.1",
"react-css-blur": "^1.1.1",
"react-dom": "^16.5.1",
"react-markdown": "^4.0.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz",
"react-native-blur": "^3.2.2",
"react-native-camera-roll-picker": "^1.2.3",
"react-native-dialog": "^5.4.0",
"react-native-simple-markdown": "^1.1.0",
"react-native-web": "0.9.0",
"react-native-web-svg": "1.0.0",
"react-navigation": "~2.3.1",
"sentry-expo": "^1.11.0",
"sweetalert": "2.1.2",
"uglifyjs-webpack-plugin": "1",
"webpack": "^4.0.0",
"webpack-dev-server": "^3.1.10",
"ws": "^6.0.0"
}
And now I would like to know and understand what I should change web-wise to make my yarn run web script work again, basically.
//web/webpack.config.js
const path = require("path");
const webpack = require("webpack");
const appDirectory = path.resolve(__dirname, "./");
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// 'node_module'.
const babelLoaderConfiguration = {
test: /\.js$/,
// Add every directory that needs to be compiled by Babel during the build.
include: [
path.resolve(appDirectory, "src"),
path.resolve(appDirectory, "node_modules/react-navigation"),
path.resolve(appDirectory, "node_modules/react-native-tab-view"),
path.resolve(appDirectory, "node_modules/react-native-paper"),
path.resolve(appDirectory, "node_modules/react-native-vector-icons"),
path.resolve(appDirectory, "node_modules/react-native-safe-area-view"),
path.resolve(appDirectory, "node_modules/#expo/samples"),
path.resolve(appDirectory, "node_modules/#expo/vector-icons"),
path.resolve(appDirectory, "node_modules/react-native-platform-touchable"),
],
use: {
loader: "babel-loader",
options: {
// cacheDirectory: false,
babelrc: false,
sourceMaps: true,
// minimize: false,
// Babel configuration (or use .babelrc)
// This aliases 'react-native' to 'react-native-web' and includes only
// the modules needed by the app.
plugins: [
"expo-web",
"react-native-web",
"transform-decorators-legacy",
["transform-runtime", { helpers: true, polyfill: true, regenerator: true }],
],
// The 'react-native' preset is recommended to match React Native's packager
presets: ["react-native"],
},
},
};
// This is needed for loading css
const cssLoaderConfiguration = {
test: /\.css$/,
use: ["style-loader", "css-loader"],
};
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[ext]",
},
},
};
const ttfLoaderConfiguration = {
test: /\.ttf$/,
use: [
{
loader: "file-loader",
options: {
name: "./fonts/[hash].[ext]",
},
},
],
include: [
path.resolve(appDirectory, "./src/assets/fonts"),
path.resolve(appDirectory, "node_modules/react-native-vector-icons"),
],
};
module.exports = {
// your web-specific entry file
entry: path.resolve(appDirectory, "src/index.js"),
devtool: "#eval-source-map",
// mode: 'development',
// configures where the build ends up
output: {
filename: "bundle.js",
publicPath: "/assets/",
path: path.resolve(appDirectory, "./app/assets"),
},
module: {
rules: [
babelLoaderConfiguration,
cssLoaderConfiguration,
imageLoaderConfiguration,
ttfLoaderConfiguration,
],
},
plugins: [
// process.env.NODE_ENV === 'production' must be true for production
// builds to eliminate development checks and reduce build size. You may
// wish to include additional optimizations.
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/206#issuecomment-358015555
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"), //JSON.stringify("production")
__DEV__: process.env.NODE_ENV === "production" || true,
}),
],
resolve: {
// If you're working on a multi-platform React Native app, web-specific
// module implementations should be written in files using the extension
// '.web.js'.
symlinks: false,
extensions: [".web.js", ".js", ".json"],
alias: {
"./assets/images/expo-icon.png": "./assets/images/expo-icon#2x.png",
"./assets/images/slack-icon.png": "./assets/images/slack-icon#2x.png",
"#expo/vector-icons": "expo-web",
expo: "expo-web",
"react-native$": "react-native-web",
'react-native-svg$': 'react-native-web-svg',
"babel-runtime/regenerator": require.resolve("babel-runtime/regenerator"),
},
},
};
Thanks to all.