I am having an issue adding webpack to an existing React project. Previously, the project was rendered server-side with next.js. However, there seems to be something wrong with my webpack config. Whenever I try to build my project, it fails with seemingly valid ES6 code:
ERROR in ./src/components/shared/menu/component.js
Module build failed: SyntaxError: Unexpected token (8:12)
6 |
7 | export default class Menu extends PureComponent {
> 8 | propTypes = {
| ^
9 | items: PropTypes.arrayOf(PropTypes.shape({
10 | name: PropTypes.string.isRequired,
11 | action: PropTypes.func.isRequired,
My webpack.config.js
const path = require('path');
module.exports = {
entry: './src/pages/index/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS
]
}
]
},
devServer: {
contentBase: path.resolve(__dirname, "dist")
}
};
My .babelrc
{ "presets": ["es2015", "react"] }
I've already tried search on SO and google, but cannot find anyone else experiencing the same issue. Please advise! Thanks!
1) run: npm install --save-dev babel-plugin-transform-class-properties
2) Update your .babelrc file:
{ "presets": ["es2015", "react"], "plugins": ["transform-class-properties"] }
That way, babel will also transform class properties as specified in the README: https://www.npmjs.com/package/babel-plugin-transform-class-properties
Also, make sure to use the keyword static when you define propTypes inside a class (so that it will be declared on the class itself, not on its prototype)
Use babel polyfill plugin, and have it included in webpack before your entry points, that means have entry point as array and first elemen is 'babel-polyfill' and second element is your index.js
You could also have require or import babel-polyfill as the first line index.js but only needed to have it once either in webpack or index file.
Related
I'm trying to integrate a connection to Ledger nano X devices, into a native Swift package. Unfortunately Ledger only provide an SDK as a ReactNative module. I dislike ReactNative and really don't want to integrate it into my entire Swift package, and force it onto my users, just for this one library.
I've had limited success in the past converting NodeModules into plain .js files that I can run directly with iOS's JavascriptContext. I've used webpack to bundle it up into a single plain js file (no require, import, export etc keywords). Adding a native Swift wrapper around that lets me keep all the messy dev setup and tools out of my project and just leverage the plain JS when needed for small use-cases. I've very little experience with this and what i've done in the past isn't working, hours of googling hasn't gotten me any closer.
Building the entire Ledgerjs with webpack was throwing up errors, since I only need pieces of it I started trying to get one of the sub-packages #ledgerhq/react-native-hw-transport-ble to build. I forked the project and added this webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
"ledger_transport_ble": ['./src/awaitsBleOn.ts', './src/BleTransport.ts', './src/monitorCharacteristic.ts', './src/remapErrors.ts', './src/timer.ts', './src/types.ts']
},
mode: 'production',
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(js|jsx)$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
devtool: 'source-map',
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx'],
modules: ['node_modules'],
fallback: {
"stream": require.resolve("stream-browserify")
}
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
library: ['[name]'],
libraryTarget: "var"
},
plugins: [
new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] })
],
};
with this .babelrc
{
"presets": [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-flow"
]
}
and I get back this error:
ERROR in ./node_modules/react-native-ble-plx/index.js 11:7
Module parse failed: Unexpected token (11:7)
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
| export { State, LogLevel, ConnectionPriority, ScanCallbackType, ScanMode } from './src/TypeDefinition'
|
> export type {
| Subscription,
| DeviceId,
# ./src/BleTransport.ts 87:29-60
Instructions online where to add the .babelrc file that I added above, but it made no difference. Have I missed a step somewhere? Or is there something else I should be doing?
I'm using create-react-app to create a component library using Storybook JS. The aim is to publish a NPM package where these components can be used in other projects. SASS is being used for this library, with global variables defined and imported into the src/index.js file.
I'm at the point of testing my NPM package, and trying to bundle it with Webpack V4. This has been semi-successful using npm link on another local project. However, I'm facing an issue with MiniCssExtractPlugin where the styles are not being inserted at all into the HEAD of this project.
The SASS stylesheets are converted into CSS and added to the dist/ folder of my component library project with no issues. But these don't get applied anywhere when importing components via the NPM package to my other project, e.g. import { Button } from '#my-account/components';
There are no issues on my dev environment when using style-loader, and the styles are inserted straight into the DOM with a <style> tag. I'm sure I must be missing something, but I feel like I've exhausted everything to try diagnose this. Is create-react-app not compatible with this plugin? Or are styles not automatically injected to the HEAD of projects via NPM packages with this plugin?
The styling does work if I import the file from the NPM package into my local project, e.g. import '#my-account/components/dist/main.cd2be00655e79c5077cb.css'; - but this doesn't seem maintainable if styles are regularly updated and the file uses a hash in its name?
I attempted to add HtmlWebpackPlugin to create an index.html file, but this didn't resolve the issue.
Any help would be greatly appreciated!
webpack.config.prod.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve('dist'),
filename: 'index.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.js?$/,
exclude: /(node_modules)/,
use: 'babel-loader',
}
],
rules: [
{
test: /\.scss$/,
sideEffects: true,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-resources-loader',
options: {
resources: require(path.join(process.cwd(), 'src/assets/sass/WebpackStyles.js')),
hoistUseStatements: true
}
}
],
},
]
},
resolve: {
extensions: ['.js'],
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[hash].css'
})
]
};
Component libraries regularly require css to be imported alongside the js in order to work properly. If you update your plugins as:
new MiniCssExtractPlugin({
filename: '[name].css'
})
Then you can instruct consumers of your library to add import '#my-account/components/dist/main.css' which is a little easier to swallow. I'm not sure there's a magical way to have the styles just show up without extensive custom webpack loaders in your consumers.
I started from a configuration consisting of both webpack 3 and a similarly old babel version. It can be found in the following repo:
https://github.com/konradmi/react-loadable-ssr-code-splitting
I updated both webpack and babel to their latest versions, as well as all the node modules, and migrated the old configuration accordingly. This issue could stem from any of these.
Once I finished migrating, I noticed all the babel plugins traverse my webpack configs files (which are in a separate nested folder) instead of the actual js source files which are properly processed by webpack. (I verified it by doing some logging inside of the babel plugins).
The result is the same regardless of whether I'm using .babelrc or not.
The webpack config files used to be at the root of the project as you can see in the repo I linked to above, and now they are inside of a nested "config" folder.
At first I thought it might be the cause of this issue, so I tried the following:
Using path.resolve() in the entry point in order to use an absolute path to make sure it wouldn't possibly be re-interpreted by babel from a string relative to who knows where.
Putting the webpack config files back in the root of the project and building from that path.
In all the variations I've tried - webpack always does its job perfectly, while babel is traversing the wrong files. I'm not even sure how it's possible, babel-loader should be traversing the files which it got from the previous webpack rule, which emitted the correct files.
Here's my current Webpack 4 config files concatenated into 1 file and stripped of irrelevant rules and plugins for your convenience:
const webpack = require('webpack')
const path = require('path')
const webpackNodeExternals = require('webpack-node-externals')
module.exports = {
name: 'server',
target: 'node',
externals: [webpackNodeExternals()],
entry: './src/server.tsx',
output: {
filename: 'bundle.js',
chunkFilename: '[name].js',
path: path.resolve(__dirname, '../build')
},
mode: 'development',
stats: 'verbose',
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
babelrc: false,
presets: [
[
'#babel/env',
{
'targets': {
'browsers': ['last 2 versions']
},
'debug': false
}
],
'#babel/preset-react'
],
plugins: [
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-transform-object-assign',
'react-loadable/babel'
]
}
}
]
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
}
}
I was importing webpack in my server source code, the files babel was going over were webpack imports which I added there in the source code. It couldn't find anything else other than those imports because due to previous rules webpack was exporting a bundle with evals containing the processed code (dev mode settings). The babel plugin wasn't looking for eval statements, so the only thing I could see was the processing of webpack related imports.
When I build react project with webpack, I got an 'Unexpected token' error
webpack --progress
ERROR in ./src/App.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token (13:13)
11 | }
12 |
> 13 | onSearch = (e) => {
| ^
14 | console.log('click');
15 | }
I thought my project doesn't transpile es6 codes to es5 because wrong setting of webpack.config.js, but I can't find what's wrong.
webpack.config.js
module.exports = {
entry: __dirname + "/src/App.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
},
module: {
rules: [{
test: /\.js?$/,
loader: 'babel-loader',
query: {
cacheDirectory: true,
presets: ['react', 'es2015']
}
}]
}
}
Install babel-preset-stage-2 package and try this:
.babelrc
{
"presets": ["es2015", "react", "stage-2"]
}
webpack.config.js
...
presets: ["es2015", "react", "stage-2"]
...
In the future, we might not use the babel's state presets as this Removing Babel's Stage Presets article said.
However, for now, it worked really well
What's Babel's Stage Presets:
A Babel preset is a shareable list of plugins.
The official Babel Stage presets tracked the TC39 Staging process for
new syntax proposals in JavaScript.
Each preset (ex. stage-3, stage-2, etc.) included all the plugins for
that particular stage and the ones above it. For example, stage-2
included stage-3, and so on.
I followed this tutorial to setup a react project and I thought I nailed it. After installing everything works as it should.
But I have to create a website that uses foundation as a front-end lib. The tutorial I linked above runs server.js when I run npm start but foundation-cli uses the same command for compiling all foundation sass code to css.
At the moment when I run npm start it only runs react and not foundation. How can I run foundation too? can I make it so that it'll automatically run both?
Since you are already using Webpack, I would suggest you to use one of the loaders for it and compile your CSS with it. This one seems like it can do that for you.
This is not tested, but I assume you can add it to your Webpack config like this:
// be sure to install it with
// npm install sass-loader node-sass --save-dev
const path = require('path');
module.exports = {
context: path.join(__dirname, 'src'),
entry: [
'./main.js',
],
output: {
path: path.join(__dirname, 'www'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
'babel-loader',
],
},
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}
}
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
},
};