BabelJS and Webpack config for maximum possible compatibility - javascript

My website must work with the most basic phone browsers imaginable, because my user base is rural Ethiopian children on very, very basic handsets. (I am using jquery to save handset battery, as most are 'recycled', second/third/fourth-hand and ancient, and I'm being extremely careful about data costs.)
I am trying to set up Babel + Webpack to transpile for the lowest possible supportable target, but I misunderstand the Babel docs, (eg, I started with #babel/preset-env and no targets, as I assumed that not targeting meant maximum compatibility, but this doesn't polyfill), and can't test against my enormous range of target handsets and browsers.
Will the below config produce and bundle Javascript that'll run on the maximum possible range of browsers? Is there any way to make it more compatible?
I have useBuiltins=usage - will the webpack config below detect repeated imports, and tree shake? If not what do I need to change, or would useBuiltins=entry and require('core-js');require('regenerator-runtime/runtime') in my index.js be better?
Using import or require to import bootstrap generates a larger file than the bootstrap distribution, even though I make no reference to it in the JS. How can I get tree-shaking working? Should I not use jquery via npm? EDIT: Tree shaking only happens on PROD builds, and seems to be working with the below configuration.
Can I safely use the latest jquery and rely on the polyfilling, rather than 1.12, which has security issues but I'm using as it works on much more browsers?
Can I remove #babel/cli, as webpack is running babel? (It works, I just want to be sure I'm getting every ounce of polyfill and compatibility, happy to run babel CLI if better.)
Any other missed opportunities/recommendations?
(If relevant, I do not need any chunking - this is a simple app and I am caching indefinitely. I am writing this into a Django static folder, and Django + whitenoise are handling filename fingerprinting and HTTP compression. I will at some point add JS unit tests. I am importing bootstrap JS for polyfills and tree-shaking (although Bootstrap doesn't seem to be shaking), but loading the bootstrap CSS directly from the HTML to avoid cache misses when I update the app.)
packages.json:
{
...
"scripts": {
"start": "webpack-dev-server --open --mode development",
"build": "webpack --mode production",
},
"devDependencies": {
"#babel/cli": "^7.10.1",
"#babel/core": "^7.10.2",
"#babel/plugin-proposal-class-properties": "^7.10.1",
"#babel/preset-env": "^7.10.2",
"axios": "^0.19.2",
"babel-loader": "^8.1.0",
"bootstrap": "^4.4.1",
"jquery": "^1.12.4", // insecure old version but more compatible
"popper.js": "^1.16.1",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"#babel/polyfill": "^7.10.1",
"core-js": "^3.6.5"
}
}
.babelrc:
{
"presets": [
[
"#babel/env",
{
"targets": "cover 100%",
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
],
"plugins": ["#babel/plugin-proposal-class-properties"]
}
webpack.config.js:
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
output: {
filename: 'app.js',
publicPath: "/static/",
path: path.join(__dirname, '../djangoproj/app/static/app')
},
devServer: {
writeToDisk: true, // Django serves the content
}
};
index.js:
import $ from 'jquery';
import bootstrap from 'bootstrap'
import popper from 'popper.js'
import {Controller} from './controller';
$(document).ready(function() {
const app = new Controller()
})
controller.js:
import {View} from './view';
import {ActivityStore, ElementStore} from './store';
import {Api} from './api';
export class Controller {
constructor() {
this.state = {}
this.api = new Api(config)
// and so on..
Update: I have decided not to progressively polyfill (using <script type="module" ..) as #tfr recommends below, as it is more important to me to test for the lowest phones than optimise newer phones. This is more likely if I'm running the polyfills on my more modern test devices. That said, core-js claims to only polyfill if necessary, so I'm not sure whether nomodules really makes a difference beyond bundle size (so much of my understanding of this technology is choosing which bit of info I trust my understanding of more). I also decided to load Bootstrap and Popper direct from the browser rather than bundled. I am looking into generating a vendor.js but not sure there are any advantages, except perhaps that they'll load before the polyfills in my bundle.
Enormous thanks.

Normally the best way would be to bundle dual (modern browser and legacy) the same time, so you don't have to polyfill modern devices. Take a look at this working polyfill example.
Thats how you could load es6 for modern and es5 bundle for legacy browser:
<!-- main bundle -->
<script type="module" src="/assets/scripts/main.js"></script>
<!-- polyfilled legacy browser -->
<script nomodule src="/assets/scripts/main.legacy.js" defer="defer"></script>
And here the main answer to your question:
Babel Config
============
const legacy = {
presets: [
["#babel/preset-env", {
targets: {
browsers: [
"> 1% in ET", // make sure its the right country code
"ie >= 6",
"not dead"
]
},
useBuiltIns: "usage",
corejs: 3,
}]
],
plugins: [
"#babel/plugin-syntax-dynamic-import",
"transform-eval"
],
comments: false,
cacheDirectory: path.join(CACHE_PATH, 'babel-loader')
};
Webpack Config
==============
const prod = {
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
exclude: [
/node_modules/
],
use: {
loader: 'eslint-loader',
},
},
{
test: /\.js$/,
exclude: [
/node_modules/
],
loader: "babel-loader",
options: babelConfig
}
]
},
resolve: {
extensions: ['.js', '.json'],
}
};
snippets from https://github.com/unic/darvin-webpack-boilerplate/blob/master/webpack/settings/javascript-legacy/index.js

Related

Bundle JS with rollup and Babel for use in IE11

I try to bundle two JavaScript modules, so that the resulting code works in IE11. For this I have setup a yarn/npm project which uses rollup.js for bundling and Babel for transpiling. Everything works fine until I add the (non-dev) dependency core-js.
Here the details:
1 Setup before adding core-js
JS files
src/main.js
src/utils.js
Config files
package.json
{
"name": "rollup_for_ie",
"devDependencies": {
"#babel/core": "^7.11.1",
"#babel/preset-env": "^7.11.0",
"#rollup/plugin-babel": "^5.2.0",
"#rollup/plugin-node-resolve": "^9.0.0",
"rollup": "^2.24.0"
},
}
rollup.config.js
import resolve from '#rollup/plugin-node-resolve';
import babel from '#rollup/plugin-babel';
export default {
input: 'src/main.js',
output: {
file: 'dist/main.js',
format: 'iife'
},
plugins: [
resolve({
browser: true
}),
babel({
exclude: "node_modules/**", // only transpile our source code
babelHelpers: 'bundled'
})
]
};
babel.config.js
module.exports = {
presets: [
[
"#babel/preset-env",
{
targets: {
browsers: "> 0.5%, ie >= 11"
},
modules: false,
spec: true,
useBuiltIns: "usage",
forceAllTransforms: true,
corejs: 3
}
]
],
};
When I run rollup -c I get warnings about unresolved dependencies, but a bundled file dist/main.js with the (used) stuff from the src directory is generated. The resulting file works even in modern browsers like Chrome. So far so good.
Problems after adding core-js
However the bundled file is not yet IE11 ready: In IE I get errors like Object doesn't support property or method 'getOwnPropertySymbols'. So the polyfills from core-js need to be added.
For this I install core-js as a prod dependency. Now rollup -c doesn't give me warnings - but the resulting dist/main.js begins like
(function (exports) {
'use strict';
var $ = require('../internals/export');
.
.
.
which as a script can not neither Chrome nor IE execute! It looks like that somehow the presence of the core-js library throws the rollup bundler off.
How can I fix my setup so that the resulting dist/main.js works as non-module script in Chrome and IE11?
I think as you enabled the option useBuiltIns: "usage" which means it will append code from corejs into your module files which is written with cjs style. So you have to add this plugin #rollup/plugin-commonjs to convert back to esm, then it will work:
import commonjs from '#rollup/plugin-commonjs';
export default {
// ...
plugins: [
// ...
commonjs(),
]
};

How to resolve 'class constructor cannot be invoked without new' error when building with svelte, babel, and webpack

I'm trying to get svelte, webpack, and babel to work together. I am producing the minified bundle, however, this bundle is throwing errors upon loading it up in the browser. This needs to be compatible with IE11 while using ES6 syntax.
I get
Class constructor I cannot be invoked without 'new'
The pertinent parts of my webpack looks as follows
{
test: /\.(js|jsx|mjs|svelte)?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: path.resolve(__dirname, 'babel.config.js')
}
}
]
},
{
test: /\.svelte$/,
exclude: /node_modules/,
use: {
loader: "svelte-loader",
options: {
emitCss: false,
hotReload: false
},
},
},
babel.config is as follows
module.exports = {
plugins: [
'#babel/plugin-proposal-class-properties',
'angularjs-annotate',
'lodash'
],
presets: [
['#babel/preset-env', {
useBuiltIns: 'usage',
corejs: { version: 3, proposals: true }
}],
'#babel/preset-react'
]
};
The svelte file itself is pretty basic
<script>
export let name = "World";
</script>
<h1>Hello {name}!</h1>
UPDATE
I can get it to run by excluding transform-classes in babel config
exclude: ['transform-classes'],
However, this of course breaks IE11.
You will need to update the webpack-cli and html-webpack-plugin versions in your package.json:
"webpack-cli": "^4.5.0",
"html-webpack-plugin": "^5.1.0",
Then, delete your node_modules and package-lock.json files and run a new npm install
Simply do this:
$ yarn remove webpack-cli && yarn add --dev webpack-cli
This will remove the old cli version, re-install the new one and compile everything afresh. Problem solved

External React component library JSX Babel wont compile

I'm trying to extract certain compoennts in my React Application to a separate reusable component library.
What I've done, is cloned this project: https://rinsejs.io/ and subsequently referenced the github repo in my main projects package.json
entry in package json of core project
"react-sharedlib": "git+ssh://git#github.com/myrepos/react-sharedlib.git#master",
Webpack.config inside react-sharedlib
// Path is in Node for free and will make simple resolving of directories no
// matter which part of your file system your library lives in
const path = require('path');
// Webpack is just a bunch of keys on module.exports!
module.exports = {
// This is where our app starts. This is why we hnpm install --save-dev babel-core#6.4.5ave done all this importing
// and exporting, to get to here
entry: './src/index.js',
// module (I know it's a bit weird to hanpm install --snpm install --save-dev babel-preset-es2015#6.3.13ave-dev babel-loader#6.2.1ve module.exports.module) is where we
// define all the rules for how webpack will deal with thing.
module: {
// rules takes an array, each item containing the respective rules
rules: [
{
// First up, our JavaScript rules.
// If you want to use the .jsx extension, you can change this line to
// test: /\.jsx?$/,
// The ? in the regex just means "optional"
test: /\.js$/,
// Don't bother spending time transpiling your installed packages
// exclude: /node_modules/,
// This is where we tell webpack to use babel to transpile our JS.
// The configuration can go here, but in this case it's in ./babelrc.js
use: {
loader: 'babel-loader',
},
},
{
// I haven't used SCSS in the base example, but it's here for you if you
// want! If you want to use CSS, you can change this next like's regex to
// /\.(css|scss)$/ or even just /\.css$/
test: /\.scss$/,
use: [
// These three libraries are commonly used together to turn Sass into
// CSS, then be able to load the CSS directly with imports. From there
// It gets put in the DOM for you.
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
],
},
{
// Some image formats so you can import images
test: /\.(png|gif|jpg|svg)$/,
use: {
loader: 'url-loader',
options: {
limit: 50000,
},
},
},
],
},
// Here we define explicitly the file types we intend to deal with
resolve: {
extensions: ['.scss', '.js', '.json', '.png', '.gif', '.jpg', '.svg'],
},
// This is where we define how everything gets output.
// dist is a common output folder, and it should be gitignored. The build can
// be run after publishing so you don't wind up with it in source control
output: {
path: path.resolve(__dirname, 'dist/'),
publicPath: '',
// You can do fun things here like use the [hash] keyword to generate unique
// filenames, but for this purpose rinse.js is fine. This file and path will
// be what you put in package.json's "main" field
filename: 'rinse.js',
// This field determines how things are importable when installed from other
// sources. UMD may not be correct now and there is an open issue to fix this,
// but until then, more reading can be found here:
// https://webpack.js.org/configuration/output/#output-librarytarget
libraryTarget: 'umd',
},
};
Babel config inside shared-lib:
{
"presets": ["#babel/env", "#babel/preset-react", "es2015", "react"],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
Package.JSON inside shared-lib:
{
"name": "react-sharedlib",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"dependencies": {
"#babel/preset-react": "^7.0.0",
"babel-core": "^6.4.5",
"babel-loader": "^6.2.1",
"babel-preset-es2015": "^6.3.13"
},
"devDependencies": {
"#babel/plugin-syntax-dynamic-import": "^7.2.0",
"babel-preset-react": "^6.3.13"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/myrepos/react-sharedlib.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/myrepos/react-sharedlib/issues"
},
"homepage": "https://github.com/myrepos/react-sharedlib#readme"
}
When I try to build my project I get this error. (Which looks like a problem with babel in some capacity, not being able to reference the JSX syntax or needing a loader configured. Anyone any idea what I'm doing wrong here, or what other things to try? As you can see from my dependencies I've had a go at installing Babel loaders, but to no avail. I assume I may just be missing a piece of configuration somewhere to get it to recognise the HTML inside the JS file.
ERROR in /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/components/Button/Button.js 23:8
Module parse failed: Unexpected token (23:8)
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
| // along without changing any of the contents. This is basically just creating
| // a copy to pass along
> return <ButtonWrapper {...props}>{props.children}</ButtonWrapper>;
| }
|
# /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/components/Button/index.js 2:0-30 4:15-21
# /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/index.js
# ./app/App.js
# ./index.js
Latest version of React btw.
Webpack 4.29.6
Update: **
Following on from the answer posted below, my shared library webpack.config.js file now contains this entry which unfortunately made no difference.
rules: [
{
// First up, our JavaScript rules.
// If you want to use the .jsx extension, you can change this line to
// test: /\.jsx?$/,
// The ? in the regex just means "optional"
test: /\.js$/,
// Don't bother spending time transpiling your installed packages
// exclude: /node_modules/,
// This is where we tell webpack to use babel to transpile our JS.
// The configuration can go here, but in this case it's in ./babelrc.js
use: {
loader: 'babel-loader',
options: {
babelrcRoots: [".", "node_modules/react-sharedlib"]
}
},
}
CORE PROJECT .babelrc:
{
"presets": ["#babel/env", "#babel/preset-react"],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
SHARED PROJECT .babelrc:
{
"presets": ["#babel/env", "#babel/preset-react", "es2015", "react"],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
By default, Babel assumes that .babelrc files in node_modules are ignored, because they were probably published on accident, and usually they reference plugins and presets that are in their devDependencies and thus probably aren't installed. The config could even be for a different version of Babel, so even if they were all installed, they still might not work.
This means you need to either:
Tell Babel explicitly that node_modules/react-sharedlib is safe to load the config for.
Configure your application's Babel config to compile that specific node_modules/react-sharedlib.
The first can be accomplished by specifying:
babelrcRoots: [".", "node_modules/react-sharedlib"],
in babel-loader's options.
The second would require using a babel.config.js config file in your application, and exporting your project-wide plugins there, so that they apply to any file you pass to Babel.
The Babel docs for config files are also a good place to review.

Babel 7 - ReferenceError: regeneratorRuntime is not defined

I have an application that is a node backend and a react frontend.
I get the following error when i try to build/run my node application.
Node: v10.13.0
Error:
dist/index.js:314
regeneratorRuntime.mark(function _callee(productId) {
^
ReferenceError: regeneratorRuntime is not defined
.babelrc
{
"presets": [ [
"#babel/preset-env", {
"targets": {
"node": "current"
},
}
], "#babel/preset-react"],
"plugins": [
"#babel/plugin-proposal-class-properties"
]
}
webpack.config.js
{
mode: "development",
entry: "./src/index.js",
target: "node",
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
stats: {
colors: true
},
devtool: "source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js",
sourceMapFilename: "index.js.map"
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
}
],
},
node: {
__dirname: false,
__filename: false,
},
"plugins": [
new CleanWebpackPlugin(),
new WebpackShellPlugin({
onBuildStart: [],
onBuildEnd: ["nodemon dist/index.js"]
}),
]
},
package.json
"dependencies": {
"connect": "^3.6.6",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"express": "^4.16.4",
"hellojs": "^1.17.1",
"i18n-iso-countries": "^3.7.8",
"morgan": "^1.9.1",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"request": "^2.88.0",
"request-promise-native": "^1.0.5",
"serve-static": "^1.13.2",
"vhost": "^3.0.2"
},
"devDependencies": {
"#babel/cli": "^7.1.5",
"#babel/core": "^7.1.6",
"#babel/plugin-proposal-class-properties": "^7.1.0",
"#babel/preset-env": "^7.1.6",
"#babel/preset-react": "^7.0.0",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"clean-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^1.0.1",
"eslint": "^5.9.0",
"eslint-config-google": "^0.10.0",
"eslint-loader": "^2.1.1",
"eslint-plugin-react": "^7.11.1",
"extract-loader": "^3.0.0",
"file-loader": "^2.0.0",
"node-sass": "^4.10.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^4.26.0",
"webpack-cli": "^3.1.2",
"webpack-node-externals": "^1.7.2",
"webpack-shell-plugin": "^0.5.0"
}
Updated Answer:
If you are using Babel 7.4.0 or newer, then #babel/polyfill has been deprecated. Instead, you will want to use the following at the top of your main js file (likely index.js or similar):
import "core-js/stable";
import "regenerator-runtime/runtime";
Install these packages either with npm:
npm install --save core-js
npm install --save regenerator-runtime
or with yarn:
yarn add core-js
yarn add regenerator-runtime
Original Answer:
I just encountered this problem and came across the following solution:
In package.json I had #babel/polyfill as a dependency. However, in my index.js (My main js file) I had neglected to place the following line at the the top:
import '#babel/polyfill'
Once I imported it, everything worked fine.
I did not need to install babel-runtime as other answers are suggesting.
Babel 7.4.0 and later
There are two main configurations - one for apps and one for libraries.
Option 1: App
When to use: ✔ for applications ✔ global scope polyfills ✔ smallest bundle size ✔ selective inclusion via targets ✔ No need to process node_modules for polyfills
"presets": [
[
"#babel/preset-env",
{
"useBuiltIns": "usage", // alternative mode: "entry"
"corejs": 3, // default would be 2
"targets": "> 0.25%, not dead"
// set your own target environment here (see Browserslist)
}
]
]
Install dependencies:
npm i --save-dev #babel/preset-env
npm i regenerator-runtime core-js // run-time dependencies
// regenerator-runtime: transform (async) generators and `async`/`await`
// core-js: other ECMAScript features like Promise, Set, etc.
#babel/preset-env selectively includes polyfills for targets, specified by a Browserslist query. There are two modes - try usage first (more convenient), else entry (more flexible and robust):
useBuiltIns 'usage': no need to import anything manually. All polyfills are added automatically based on their code usage in a file.
useBuiltIns 'entry': Add these import entries once (!) in your app - akin to #babel/polyfill:
import "regenerator-runtime/runtime";
import "core-js/stable"; // or more selective import, like "core-js/es/array"
Extension
For advanced cases, you might use #babel/transform-runtime (dev) and #babel/runtime (run-time) only for Babel helpers to reduce bundle size a bit more - called helper aliasing.
Option 2: Library
When to use: ✔ for libraries ✔ no global scope pollution ✔ includes all polyfills, not selective ✔ bigger bundle size neglectable
"plugins": [
[
"#babel/plugin-transform-runtime",
{
"regenerator": true,
"corejs": 3
}
]
]
Install compile-time and run-time dependencies:
npm i --save-dev #babel/plugin-transform-runtime // only for build phase
npm i #babel/runtime // runtime babel helpers + just regenerator runtime
// OR (choose one!)
npm i #babel/runtime-corejs3
// also contains other JS polyfills (not only regenerator runtime)
// depends on core-js-pure ("ponyfills"/polyfills that don't pollute global scope)
See #babel/plugin-transform-runtime, #babel/runtime, #babel/runtime-corejs.
Extension
You can additionally use #babel/preset-env for syntax transpilation only, with useBuiltIns: false. As the library option does not use global polyfills, you might want to transpile node_modules as well - see the absoluteRuntime option.
Closing notes
Breaking Change: #babel/polyfill is deprecated starting with Babel 7.4.0.
Legacy: If you can't switch to core-js#3, set corejs option to 2 (see migrations). Install #babel/runtime-corejs2 in case of option 2 (#babel/plugin-transform-runtime).
Excellent summary in #9853 by Jovica Markoski
Currently, the library approach doesn't take selective targets into account - meaning you take locally scoped polyfills at the price of bigger bundle size (including all polyfills).
babel-polyfills is a new, experimental approach to inject different polyfills (not just core-js) with different strategies.
This also allows to selectively include locally scoped polyfills.
There is already a very good answer here (originally posted on the Babel6 question) which I will just translate to Yarn. Basically, you need babel runtime (NOT as a dev dependency) and the plugin transform-runtime
yarn add #babel/runtime
yarn add -D #babel/plugin-transform-runtime
And, in .babelrc, add:
{
"presets": ["#babel/preset-env"],
"plugins": ["#babel/transform-runtime"]
}
I had this error in my react project with webpack 4 and this was preventing the whole project to get rendered.
This is how I solved it:
Install plugin-transform-runtime:
npm install #babel/plugin-transform-runtime -D
Add plugin-transform-runtime to the plugin's list in the .babelrc file:
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
["#babel/transform-runtime"] // <= Add it here
]
}
For me worked:
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
esmodules: true,
},
},
],
],
}
I just solved this error when I imported babel-polyfill directly into the file that shows the error, for example, the error says "ReferenceError: regeneratorRuntime is not defined at /dist/models/usersSchema.js", so I use this in my usersSchema.js file:
require("babel-polyfill");
(you can use import "babel-polyfill";as well)
You will need to have the regeneratorRuntime.
Install this two packages - babel-plugin-transform-regenerator and babel-polyfill
Add the following Babel configuration via .babelrc
{
"plugins": ["transform-regenerator"]
}
React.js Users
If this issue faced you while using react (specifically while trying to use Async/Wait), then Valentino Gagliardi provided a detailed approach on his blog regarding how to address this issue

Node JS Webpack Babel with async

When trying to compile my server-side code, I get the following error:
Module parse failed: (...babel-loader-path)?{"presets":["es2015-node4","es2015"]} (...) Unexpected token (86:6)
You may need an appropriate loader to handle this file type.
This error seems to be caused by an Async function that I am trying to import. Do I need to change my webpack configuration?
My webpack config file:
const webpack = require('webpack');
module.exports = {
target: 'node',
entry: ['./server/index.js', './node_modules/webpack/hot/poll?1000'],
output: {
path: './dist',
filename: 'server.bundle.js',
libraryTarget: 'commonjs',
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
externals: [/^[a-z]/],
module: {
loaders: [{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015-node4', 'es2015'],
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015-node4', 'es2015'],
},
}
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devtool: 'source-map',
};
If you are using Webpack to compile your Node code, then that is not a good approach. You should simply use babel-node which is an amazing way to transpile your node code.
For that in your package.json do the following
"scripts": {
"dev": "node_modules/.bin/nodemon --exec babel-node server/index.js",
"prestart": "node_modules/.bin/babel server --out-dir dist",
"start": "node dist/index.js"
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.40",
"#babel/core": "^7.0.0-beta.40",
"#babel/node": "^7.0.0-beta.40",
"#babel/preset-env": "^7.0.0-beta.40",
"#babel/preset-stage-2": "^7.0.0-beta.40",
"nodemon": "^1.11.0"
}
In your .babelrc file, do the following.
{
"presets": [
"#babel/preset-env",
"#babel/preset-stage-2"
]
}
Then in your project directory create a folder called server and in that folder create a file called index.js which creates your node http server.
For a reference have a look at Babel-Node Documentation
Or have a look at this amazing small tutorial kind of example created by the awesome folks at Babel Example Node Server Using Babel-Node
P.S: In the package.json file the npm run dev watches your code and npm start commands compiles your code ready to be shipped for production.
There seems to be a mis-understanding with regard to the babel preset usage. The preset you want is not the target version of javascript you want to output. For that you need to set target appropriately. Instead you needed the preset that corresponds to the version of javascript you are writing in. The presets are collections of transformers that instruct babel how to deal with specific javascript constructs.
In babel <=6 you need either: es2017 or transform-async-to-generator presets to use the async keyword. After babel 7 the recommendation is to use:
{
"presets": ["#babel/preset-env"]
}
This allows babel to support all modern java-script syntax's that have been finalized. It will then transpile to whatever syntax your target setting indicates. I personally would use a browserslist query in package.json for this so other tools like postcss automatically pick up the same target information.

Categories

Resources