Transpiling NextJS for IE 10/11; 'Weakset undefined' - reactjs

I have a NextJS website I'm building and it's great, except that it does not work in IE 10/11 because some code is not being transpiled correctly. I'm really bad with babel and webpack, and have never had to config them myself before. I've been trying to solve by reading online for two days now, and nothing seems to work for me.
The exact error I get is weakSet is not defined, and it is coming from the common.js file.
Here is my .babelrc file, located in the root of my project.
// .babelrc
{
"presets": ["next/babel"],
"plugins": [
["styled-components", {
"ssr": true,
"displayName": true,
"preprocess": false
}]
]
}
my package.json
{
"name": "bradshouse",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "next",
"build": "next build",
"start": "next start"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"next": "^7.0.2",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"react-pose": "^4.0.1",
"styled-components": "^4.0.2"
},
"devDependencies": {
"babel-plugin-styled-components": "^1.8.0"
}
}
The full repo is here if you're interested in launching it yourself. node modules are excluded, so npm install, then npm run build, then npm run start.
https://github.com/TJBlackman/Brads-House
Thanks for the help! Feel free to just link articles and I'll read them thoroughly! Thanks.
Edit: As a quick fix, I added this polyfill script to the <head> of all my pages, and it still did not fix this issue... Wat?! <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>

How to support IE 11 by transpiling node_modules code in NextJS
Original answer found in the ziet/nextjs issues thread (view here). Shout out to joaovieira <3
npm install --save-dev babel-polyfill
create a polyfill.js where ever you want it, and inside that file, import the babel-polyfill like so:
import 'babel-polyfill';
Next, if you do not have a next.config.js file, create it at your root directory. Now update your this file to include the following webpack config. Notice how it's using the polyfill file you just made. Full file example:
module.exports = {
webpack: (config) => {
// Unshift polyfills in main entrypoint.
const originalEntry = config.entry;
config.entry = async () => {
const entries = await originalEntry();
if (entries['main.js']) {
entries['main.js'].unshift('./path_to/polyfills.js'); // <- polyfill here
}
return entries;
};
return config;
}
}
Finally, if you don't have a .babelrc file in your project's root directory, create one. Inside it, use the code below that matches the version of babel you're using.
Babel 7
{
"presets": [
[
"next/babel",
{
"preset-env": {
"useBuiltIns": "usage"
}
}
]
]
}
Babel 6
{
"presets": [
[
"next/babel",
{
"preset-env": {
"targets": {
"browsers": "defaults"
},
"useBuiltIns": true
}
}
]
]
}
That's all I know. I'm not even thinking about IE 10...
Good luck!!

I am using next#9.3 with reflect-metadata, and here is my solution:
/** next.config.js > webpack **/
const pathToPolyfills = './src/polyfills.js'
// Fix [TypeError: Reflect.metadata is not a function] during production build
// Thanks to https://leerob.io/blog/things-ive-learned-building-nextjs-apps#polyfills
// There is an official example as well: https://git.io/JfqUF
const originalEntry = config.entry
config.entry = async () => {
const entries = await originalEntry()
Object.keys(entries).forEach(pageBundleEntryJs => {
let sourceFilesIncluded = entries[pageBundleEntryJs]
if (!Array.isArray(sourceFilesIncluded)) {
sourceFilesIncluded = entries[pageBundleEntryJs] = [sourceFilesIncluded]
}
if (!sourceFilesIncluded.some(file => file.includes('polyfills'))) {
sourceFilesIncluded.unshift(pathToPolyfills)
}
})
return entries
}
/** src/polyfills.js **/
// Other polyfills ...
import 'reflect-metadata'

Related

Published npm package doesn't show function hints

I have a utils function inside my published npm package that exports many functions, The functions look like this:
const createBox = ({id, width}) => {
}
Before I publish my npm package, When I enter createBox, I can see all parameters it can take but After I publish my npm package and Install it in another project, I don't get any hints and After hovering over the function All I see is an Any word.
I'm using ReactJS, my babel.config.json file:
{
"presets": [
[
"#babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
],
"#babel/preset-react"
]
}
And here is the build:
"build": "cross-env NODE_ENV=production babel src/lib --out-dir dist --copy-files --ignore __tests__,spec.js,test.js,__snapshots__",
How can I build the package so It shows all the function hints including its parameters?.
I'm assuming you are using VSCode? I think this is some annoying default. Try changing this setting in VSCode:
"javascript.implicitProjectConfig.checkJs": true

React compiler end up with Unexpected token <

I am beginner in React and I am struggling with compiler error. Let me introduce my situation. I have two independent React applications:
App A - Big ERP
App B - "Plugin" to the App A
I supposed I will develop App B as an independent application. Then, I will install it to the App A (using npm install git#github.repo/...) once I finish development of the App B. I expected I will call components from App B within the App A source code. Everything went fine until I run the compilation. I am receiving:
SyntaxError: /frontend/node_modules/connector_frontend/src/views/Connector/FormView/index.js: Unexpected token
In my /frontend/node_modules/connector_frontend/src/views/Connector/FormView/index.js there is following code:
const ConnectorFormView = ({ AppValues, secureFetch, ...rest }) => {
return (
<p>Hello world</p>
)
}
export default ConnectorFormView;
Error is ocuring at the position of <p>.
I call this functional component from App A (frontend/src/views/Connector/ConnectorNewEditView/index.js) like this
import ConnectorFormView from "connector_frontend/src/views/Connector/FormView";
const ConnectorNewEditView = () => {
return (<ConnectorFormView AppValues={appValues} secureFetch={secureFetch} />)
}
export default ConnectorNewEditView;
I tried to return just a plain text from the ConnectorFormView component like this:
const ConnectorFormView = ({ AppValues, secureFetch, ...rest }) => {
return (
'Hello world'
)
}
export default ConnectorFormView;
and it was compiled successfully, but once I return a JSX from the ConnectorFormView component the compiler get crashed.
Can anyone explain the source of this error please?
I successfully figured out the source of this problem and also I found a solution. I expected I can reuse however React component implemented in JSX. I expected, the only requirement is to install it, resp. download it in JSX form to my project using NPM. It's FALSE.
According to my research, I can reuse React components compiled from JSX to ES only. It is achievable using Babel. Another very important requiremen, it should not by installed as React application as I installed it. It must be installed as a NPM package with clearly defined set of exported components.
I found this paper https://levelup.gitconnected.com/publish-react-components-as-an-npm-package-7a671a2fb7f and I followed it step by step and finally I achieved desired result.
I can very briefly mention steps which I performed:
Implemented my custom component (mentioned above)
const ConnectorFormView = ({ AppValues, secureFetch, ...rest }) => {
return (
<p>Hello world</p>
)
}
export default ConnectorFormView;
Added the component to /src/index.js file in order to export it for host App
import ConnectorFormView from './components/ConnectorFormView';
export { ConnectorFormView };
Installed Babel and all needed presets
npm install --save-dev #babel/core #babel/cli #babel/preset-env
npm install -save #babel/polyfill
configured Babel - created file /babel.config.json with following content
{
"presets": [
[
"#babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
],
"#babel/preset-react"
]
}
Added new script to the package.json to compile React components to ES:
"build": "rm -rf dist && NODE_ENV=production babel src --out-dir dist --copy-files";
Executed npm run build to compile React components to ES. Compiled components are located in new dist folder.
Adjusted package.json that looks like this now
{
"name": "my_react_components",
"version": "0.1.0",
"private": true,
"description": "Some description",
"author": "Lukas",
"main": "dist/index.js",
"module": "dist/index.js",
"files": [ "dist", "README.md" ],
"dependencies": {
.
.
},
"scripts": {
"build": "rm -rf dist && NODE_ENV=production babel src--out-dir dist --copy-files",
.
.
.
},
"eslintConfig": {
"extends": "react-app"
},
"devDependencies": {
"#babel/cli": "^7.17.10",
"#babel/core": "^7.18.5",
"#babel/preset-env": "^7.18.2"
}
}
Pushed dist folder to the git.
Installed repository to the host project using NPM
npm install https://github.com/my_custom/react_component.git
Import and use the component from installed git repo
import ConnectorFormView from 'my_react_components';
function App() {
return (
<ConnectorFormView />
);
}
export default App;
Actually that's all. I very recommend to see the attached paper at the beginning of this answer because I maybe skipped very important info for you.

React package, invalid hook call

I'm trying to write a NPM package with some React stuff included, at the moment it's just a component and a hook. To build the package I'm using Webpack. I've added react and react-dom to the externals section to ensure that it's not included in the bundle. I've also marked react as a peerDependency in the package.json and included it as a devDependency. Still I'm getting the error Invalid hook call when trying to use the bundle in another project. I think I've tried everything that I can Google my way to (like using the package with the purpose to solve this) with no luck.
My Webpack config looks like this at the moment:
const path = require('path');
const isProduction = process.env.NODE_ENV?.toLowerCase() === 'production';
const config = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
libraryTarget: 'umd',
},
plugins: [],
module: {
rules: [
{
test: /\.(tsx?)$/i,
loader: 'ts-loader',
exclude: ['/node_modules/'],
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader',
},
],
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.graphql', '.json'],
},
externals: {
react: 'react',
'react-dom': 'react-dom',
},
};
module.exports = () => {
if (isProduction) {
config.mode = 'production';
} else {
config.mode = 'development';
}
return config;
};
The essentials from package.json looks like this:
{
...
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
...
"scripts": {
...
"build": "webpack --mode=production --node-env=production",
"build:dev": "webpack --mode=development",
...
"prepublishOnly": "npm run build"
},
...
"peerDependencies": {
"react": "16.8.0 || ^17.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
},
"dependencies": {
"#apollo/client": "^3.3.19",
"apollo-server-errors": "^2.5.0",
"joi": "^17.4.0",
"lodash": "^4.17.21"
},
"devDependencies": {
...
"react": "^17.0.2",
"react-dom": "^17.0.2",
...
}
}
The hook is very simple, it's just trying to a context created by the component using useContext, to be sure that there isn't an issue with this logic I've tried to just use setState with the same result. The hook looks somewhat like this:
function useClient(): Client {
return useContext(getContext());
}
getContext is just a function which either creates or re-uses a existing React.Context (heavily inspired by Apollo Client):
const cache = new (canUseWeakMap ? WeakMap : Map)<
typeof createContext,
Context<Client | undefined>
>();
function getContext() {
let context = cache.get(createContext);
if (!context) {
context = createContext<Client | undefined>(undefined);
context.displayName = 'ClientContext';
cache.set(createContext, context);
}
return context;
}
export default getContext;
The component where I'm trying to use the hook is a simple functional component:
const HelloWorld: FC<HelloWorldProps> = () => {
const client = useClient();
return (
<div>Hello World!</div>
);
};
What am I missing? Really appreciate the help!
EDIT:
I reproduced the issue in a small sample app with just the basics, a external package using setState and then using that package in a create-react-app with the same result:
https://github.com/ganhammar/invalid-hook-call
Thanks for all the help!
The issue was that I stopped publishing packages and instead installed the dependency locally using file:../Client. That caused duplicate instances of React since it used the local-to-the-Client-package instance of React. Publishing only the built output and then installing that dependency solved the issue for me.
I found the following answer helpful for me to realize this (linking the react dependency between the two packages) if anyone else stumbles upon this.

Snowpack is not reloading

i started to use snowpack and ran into a big problem. Snowpack is not hot reloading for me.
I tried the basic minimal template, a svelte template and a react template - Everytime the same problem. I also created on from scratch based on the getting started.
Here a my example files:
index.jsx
import React from 'https://cdn.skypack.dev/react';
import ReactDom from 'https://cdn.skypack.dev/react-dom';
ReactDom.render(
<React.StrictMode>
<div>This is working</div>
</React.StrictMode>,
document.getElementById('root'),
);
// Hot Module Replacement (HMR) - Remove this snippet to remove HMR.
// Learn more: https://www.snowpack.dev/concepts/hot-module-replacement
if (import.meta.hot) {
import.meta.hot.accept();
}
snowpack.config.js
/** #type {import("snowpack").SnowpackUserConfig } */
module.exports = {
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
},
plugins: ['#snowpack/plugin-react-refresh'],
packageOptions: {
/* ... */
},
devOptions: {
/* ... */
},
buildOptions: {
/* ... */
},
};
package.json
{
"name": "chatclient",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "snowpack dev",
"build": "snowpack build",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#snowpack/plugin-react-refresh": "^2.4.0",
"snowpack": "^3.0.11"
}
}
I hope someone can help me. Snowpack is such an amazing tool but i can't get it to work.
I found a solution
Credits
I used to run my dev environment on wsl2. Some no known reason does nodejs not hot reload when you are in wsl2 and the files are on the windows filesystem. Moved everything to my linux filesystem and i worked.
I hope someone will find this helpful!

Error: Cannot export when target is not server. with next js and zeit-NOW during deployee

I am working a react app where i am using next js and express, I have choose zeit now for servless but when i deploying this facing error Error: No serverless pages were built
next.config.js
const configuration = withTypescript(
withLess({,
target: process.env.NODE_ENV === "development" ? "server" : "serverless",
cssModules: true,
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables // make your antd custom effective
},
exportPathMap: async function(defaultPathMap) {
return {
"/": { page: "/index" },
};
},
webpack: config => {
config.plugins = config.plugins || [];
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: path.join(__dirname, "../.env"),
systemvars: true
})
];
return config;
},
})
);
module.exports = configuration;
using next version : "#types/next": "^8.0.0",
now.json
{
"version": 2,
"name": "web",
"builds": [
{ "src": "package.json", "use": "#now/next" }
],
}
inside package json
"scripts": {
"dev": "next src",
"build": "next build src",
"start": "next run build && next start src",
"export": "npm run build && next export src -o ./out",
"now-build": "next build src","
},
Getting error from zeit Now logs
preparing lambda files...
2019-04-19T17:24:04.955Z Error: No serverless pages were built. https://err.sh/zeit/now-builders/now-next-no-serverless-pages-built
at Object.exports.build (/tmp/utils/build-module/node_modules/#now/next/index.js:305:13)
at <anonymous>
please help me here to figure it out.
Thanks.

Resources