ReactJS with Fetch on older browsers - javascript

I am implementing React JS, with Webpack and Babel. However, I am having trouble getting Fetch to work with IE 11.
I have the following in my .babelrc file:
{
"presets" : ["env", "stage-0", "react"]
}
and the following in my webpack.config.js file:
var webpack = require('webpack');
var path = require('path');
var DIST_DIR = path.resolve(__dirname, 'dist');
var SRC_DIR = path.resolve(__dirname, 'src');
var config = {
entry: {
bundle: [
'babel-polyfill',
SRC_DIR + '/app/index.js',
]
},
output: {
path: DIST_DIR + '/public/js',
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: SRC_DIR,
loader: 'babel-loader'
}
]
}
};
module.exports = config;
From my understanding implementing babel-preset-env, stage-0, and babel-polyfill should have allowed for the Fetch API to be transpiled into something older browsers could understand. Is there something else that I am missing?

fetch isn't part of EcmaScript but its part of the web platform. Babel is only a compiler to write the latest Javascript. If you want to use fetch in older browsers you need a polyfill like this one
Fetch API: read more

fetch must be made available by the browser you use and is not included in babel-polyfill. If your browser doesn't support fetch, you can either fall back to using XMLHttpRequest or use a polyfill such as isomorphic-fetch.

Related

Excluding node_module from being written to the output file in webpack

I am trying to transpile es6 code to es5 using webpack and babel and in the js file I am importing jquery as below:
import $ from 'jquery';
So when I am building the code using webpack, the output file is getting the content of jquery along with the original transpiled code which I don't want to consume. I have added the exclude statement below to webpack.config.js but that doesn't seem to exclude the jquery part from getting appended.
exclude:path.resolve(__dirname, 'node_modules'),
Here's what the webpack.config.js file looks like:
var path = require('path');
module.exports = {
entry: {
copystyles: './src/copystyles.js',
docErrorReporter: './src/docErrorReporter',
},
output: {
path: path.resolve(__dirname, 'lib'),
filename: "[name].js",
},
mode:'none',
module: {
rules: [
{
test: path.join(__dirname, 'src'),
exclude:path.resolve(__dirname, 'node_modules'),
use: ['babel-loader']
}
]
}
};
Can anybody tell me if I am missing something here?
Thanks!

Babel does not transpile imported modules from 'node_modules'

I got a problem with transpiling imported modules from node_modules. Babel for some reason doesn't transpile imported module from node_modules, but transpile modules imported from src.
Here is an example repo: https://github.com/NikitaKA/babeltest
main.js
// result code contains const and let, but it shouldn't. :(
index.js
import qs from 'query-string; // not transpiled
import lib from './lib' // transpiled
const query = qs.parse(window.location.search);
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader"
}
}
]
}
};
.babelrc
{
"presets": [
["#babel/preset-env", {
"modules": false,
"targets": {
"chrome": 39
}
}],
["#babel/preset-stage-1", {
"modules": false,
"decoratorsLegacy": true,
"pipelineProposal": "minimal"
}]
],
"plugins": [
"transform-es2015-constants",
"#babel/plugin-transform-block-scoping",
"#babel/plugin-transform-runtime"
]
}
The solution in this case is to transpile the module again, this can be done by modifying the exclude property in your webpack config:
{
test: /\.js$/,
exclude: /node_modules\/(?!(es6-module|another-es6-module)\/).*/,
},
Modules es6-module and another-es6-module will no longer be ignored by webpack and will be transpiled with the rest of your source code.
See the GitHub issue on the webpack project.
Tested with webpack#3.12.0, babel-core#6.26.3 and babel-core#6.26.3
To expand upon my comments:
You really don't want to transpile all of node_modules – it'll take a long time, and most of the code there should already be ES5 (unless they're actually ES6 modules, in which case the ES6 entry point is announced as "module" in the package.json manifest).
query-string#6.x isn't, and it says so in its README:
This module targets Node.js 6 or later and the latest version of Chrome, Firefox, and Safari. If you want support for older browsers, use version 5: npm install query-string#5.
If you're using Vue, there is a simple solution. Just list your module in transpileDependencies:
vue.config.js
module.exports = {
publicPath: '',
outputDir: 'www',
transpileDependencies: [
'query-string'
],
}

How to browserify node `fs.readFileSync` to make it work in Chrome/Safari/IE?

I have a node module that uses modules that depend on fs like making use of fs.readFileSync etc. I cannot manually remove those dependencies since are at 2nd or 3rd level of the package dependencies having level 0 my root module.
Given that,
I have to run those modules in the browser, so I have tried both browserify and webpack.
My webpack configuration is the following
var path = require('path');
var webpack = require("webpack");
module.exports = {
entry: './pgapi',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
noParse: /node_modules\/json-schema\/lib\/validate\.js/,
loaders: [
{ test: /\.json$/, loader: 'json-loader' }
, {
test: /\.js$/,
loader: "transform?brfs"
}
]
},
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.js']
},
node: {
console: true,
fs: 'empty',
net: 'empty',
tls: 'empty'
},
plugins: [
//new webpack.optimize.UglifyJsPlugin(),
//new webpack.optimize.DedupePlugin(),
new webpack.DefinePlugin({
__DEV__: true
})
]
};
and I'm using browserify as alternative with the brfs transform to try to take care of the fs.readFileSync etc.
After building the bundle.js I run babel since when in Safari there is no complete compliance to ES5 strict mode and also it take cares of the arrow operator and of let and const that are not supported as well using this script:
var fs = require('fs')
var args = process.argv.slice(2);
var code=fs.readFileSync(args[0])
var res=require("babel-core").transform(code, {
plugins: [
"transform-es2015-arrow-functions",
"transform-es2015-constants",
"transform-es2015-block-scoping"]
});
console.log(res.code)
So I do like
$ webpack or $ browserify mymodule.js -o dist/bundle.js -t brfs
and then on dist/bundle.js
$ node babelify.js dist/bundle.js > out.js.
What happens then is a ReferenceError: Can't find variable: fs (see here)
that seems to be due to the fact that the brsf transform does works on static expression eval so that it does not understand variables in fs.readFileSync(varname).
I'm using MacGap in Xcode test the WebView client code on El Capitan.
How to get rid of this at build time?
I had a similar issue.
Identify which module is calling mime and find an alternative module. For me, this was url-loader which depends on mime.
I replaced it with file-loader which doesn't depend on mime, and hence not the fs. Ensure to uninstall url-loader as it will still throw the error!

Making a library importable using webpack and babel

I am trying to publish a package on npm (this one) that I am developing using webpack and babel. My code is written in ES6. I have a file in my sources, index.js, that (for the moment) exports one of my library's core components, it simply goes like this:
import TheGamesDb from './scrapers/thegamesdb';
export { TheGamesDb };
I am using webpack and babel to create a dist index.js that is my package's main file. My webpack.config.js goes like this:
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
index: ['babel-polyfill', './src/index.js'],
development: ['babel-polyfill', './src/development.js']
},
output: {
path: '.',
filename: '[name].js',
library: 'rom-scraper',
libraryTarget: 'umd',
umdNamedDefine: true
},
devtool: 'source-map',
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
]
},
target: 'node',
externals: [nodeExternals()]
};
Now when I load my package in another project and try to import my export TheGamesDb simply like this
import { TheGamesDb } from 'rom-scraper';
I get the error
Uncaught TypeError: Path must be a string. Received undefined
It is to be noted that I am importing my library in electron.
Update: Electron seems to be the main problem here and it is not even my library but a dependency that throws this error (only in Electron)
The problem wasn't any of the things in my question but node-expat not working in electron. I switched to an alternative library and it's all right now.

Error using ES7 async/await with node, webpack and babel-loader

I'm trying to use javascript ES7 syntax on the server using node.js with webpack and babel-loader (es2015 + stage-0 presets). I've gotten it to work with babel-node but when I run webpack I get the following error at the async keyword (9:22 is after the async keyword):
ERROR in ./src/server.js Module parse failed: C:\dev\node-async-sample\src\server.js
Unexpected token (9:22) You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (9:22)
I've put the code on github at https://github.com/qubitron/node-async-sample, any ideas on how to get this to work?
Here is the relevant snippet from src/server.js:
import express from 'express';
import http from 'request-promise';
let server = express();
server.get('/', async function(request, response) {
let result = await http('http://www.google.com');
response.send(result);
});
.babelrc:
{
"presets": [
"es2015",
"node5",
"stage-0"
],
"plugins": [
"transform-runtime"
]
}
and webpack.config.js:
module.exports = {
entry: [
'babel-polyfill',
'./src/server.js'
],
output: {
path: __dirname + '/dist',
filename: 'server_bundle.js'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: __dirname + '/src',
loader: 'babel-loader'
}
]
}
};
I saw a similar issue here but it has a different error message and was fixed in babel:master:
ES7 async await functions with babel-loader not working
Your src path was incorrect. You should never (like never :)) join pathes using string concatenation there is path.join for that.
{
test: /\.jsx?$/,
include: path.join(__dirname, 'src'),
loader: 'babel-loader'
}
BTW, this will fix parsing issue but you still gonna need to handle .json file loading by adding corresponding extension to resolve section and using json-loader
{ test: /\.json$/, loader: 'json-loader' }
Also you'll need to handle missing modules warning. For example fs and net.
So I do recommend you to use babel-cli to precompile server code.
babel src --out-dir dist

Categories