Object.assign Babel with external npm dep - javascript

I have an external NPM dependency that uses Object.assign. I want to use Babel, to assure compatibility with old browsers, either transforming Object.assign via helper or substituting it using another method, but it is not working.
PS: I can use a polyfill at the top of the code, i want to avoid this since it is a library (https://babeljs.io/docs/plugins/transform-object-assign/)
The dependency is : https://github.com/krux/postscribe
via var postscribe = require('postscribe');
my .babelrc conf:
{
"presets": [
["env", {
"targets": {
"browsers": ["Android 4", "iOS 7"]
}
}]
],
"plugins": ["transform-object-assign"]
}
Gulp conf:
gulp.task('adtag', function () {
// set up the browserify instance on a task basis
var b = browserify({
entries: './src/adtag/main.js',
debug: true
}).transform(babelify)
return b.bundle()
.pipe(source('smaatoAdTag.min.js'))
.pipe(buffer())
.pipe(sourcemaps.init({
loadMaps: true
}))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', gutil.log)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dist/adtag/'));
});
Is there any way to substitute Object.assign if is in a dependency and not in the main code?

Check out the docs for babelify
You could use :
browserify().transform("babelify", {
global: true,
ignore: /\/node_modules\/(?!postscribe\/)/
});

Related

How to exclude core-js using useBuiltIns: "usage"

Using babel 7.5.5, core-js 3.1.4 and webpack 4.38.0, how can I exclude core-js from transpiling?
I do not want to exclude node_modules altogether since I have libs that need transpiling
If I use exclude: /node_modules\/(core-js)/, a core-js module throws
TypeError: $ is not a function
This leaves me with two other options.
Use includes instead, include my src directory and every dependency that needs transpiling one by one
Use useBuiltIns: entry instead of usage, since in this case exclude: /node_modules/\(core-js)/ works, and import core.js at the top of main.js
Both of these options don't really seem like good solutions to me since usage is "no longer experimental" since 7.4.
Is there any way to make it work using usage? Is it a bug in either babel-loader or babel? Or is my configuration at fault?
This is my Webpack config:
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'production',
entry: {
main: ['./src/main'],
},
output: {
path: path.resolve(__dirname, './build/'),
publicPath: '/build/'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules\/(core-js)/,
use: {
loader: 'babel-loader'
},
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: 'jQuery'
},
{
loader: 'expose-loader',
options: '$'
}
]
}
]
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
};
This is my babel config:
module.exports = function (api) {
api.cache(true);
return {
presets: [
[
'#babel/preset-env',
{
corejs: {
version: 3,
},
useBuiltIns: 'usage',
}
]
],
};
};
You can reproduce the error with the following repository: https://github.com/tomm1996/usebuiltins-exclude-test
You need to exclude both core-js and webpack/buildin from the Babel transpilation.
You can use the folling exclude Regexes:
exclude : [
/\bcore-js\b/,
/\bwebpack\/buildin\b/
]
Here is also a complete babel-loader configuration with some useful comments:
{
module : {
rules : [{
test : /\.js$/,
// Some module should not be transpiled by Babel
// See https://github.com/zloirock/core-js/issues/743#issuecomment-572074215
exclude : [
/\bcore-js\b/,
/\bwebpack\/buildin\b/
],
loader : "babel-loader",
options : {
babelrc : false,
// Fixes "TypeError: __webpack_require__(...) is not a function"
// https://github.com/webpack/webpack/issues/9379#issuecomment-509628205
// https://babeljs.io/docs/en/options#sourcetype
sourceType : "unambiguous",
presets : [
["#babel/preset-env", {
// Webpack supports ES Modules out of the box and therefore doesn’t require
// import/export to be transpiled resulting in smaller builds, and better tree
// shaking. See https://webpack.js.org/guides/tree-shaking/#conclusion
modules : false,
// Adds specific imports for polyfills when they are used in each file.
// Take advantage of the fact that a bundler will load the polyfill only once.
useBuiltIns : "usage",
corejs : {
version : "3",
proposals : true
}
}]
]
}
}
}
}
See https://github.com/zloirock/core-js/issues/743#issuecomment-572074215
Edit: Also if you try to use #babel/plugin-transform-runtime:
plugins : [
// Require the Babel runtime as a separate module to avoid the duplication
// https://webpack.js.org/loaders/babel-loader/#babel-is-injecting-helpers-into-each-file-and-bloating-my-code
["#babel/plugin-transform-runtime", {
// Requires #babel/runtime-corejs3
// https://babeljs.io/blog/2019/03/19/7.4.0#migration-from-core-js-2
corejs : { version: 3, proposals: true }
}],
}
You may run into a similar error:
Uncaught TypeError: _typeof2 is not a function
at _typeof (typeof.js:8)
at eval (sockjs.js:123)
at Object.eval (sockjs.js:131)
at eval (sockjs.js:6565)
at Object../node_modules/sockjs-client/dist/sockjs.js (main.js:13790)
at __webpack_require__ (main.js:70)
at eval (webpack://PUBLIC_ENGINE/(:8000/webpack)-dev-server/client/clients/SockJSClient.js?:110:14)
at Object../node_modules/webpack-dev-server/client/clients/SockJSClient.js (main.js:13874)
at __webpack_require__ (main.js:70)
at eval (webpack://PUBLIC_ENGINE/(:8000/webpack)-dev-server/client/socket.js?:56:41)
This can be solved by excluding #babel/runtime-corejs3 from the transpilation:
exclude : [
/\bcore-js\b/,
/\bwebpack\/buildin\b/,
/#babel\/runtime-corejs3/
]

NuxtJS with Babel 7: still have spread operator in built files

I'm desperately trying to make my NuxtJS app work with IE11. I implemented babel config in many ways to build a compatible version but I still have spread operators in built pages files, as if Babel didn't transform Nuxt code.
Here is my config:
nuxt.config.js
const pkg = require('./package')
const path = require('path');
module.exports = {
mode: 'universal',
// ...
build: {
babel: {
babelrc: true
},
extend(config, ctx) {
config.resolve.modules.push(path.resolve(__dirname, 'assets'));
const svgRule = config.module.rules.find(rule => rule.test.test('.svg'));
svgRule.test = /\.(png|jpe?g|gif|webp)$/;
config.module.rules.push({
test: /\.svg$/,
loader: 'vue-svg-loader',
}, {
test: /\.js$/,
loader: 'babel-loader'
})
}
}
}
.babelrc
{
"presets": [["#babel/preset-env", { "modules": false }]],
"plugins": [
"#babel/transform-runtime",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-transform-spread",
"#babel/plugin-proposal-object-rest-spread"
],
"env": {
"test": {
"presets": [["#babel/preset-env", { "targets": { "node": "current" } }]]
}
}
}
.browserslistrc
# Browsers that we support
>0.2%
not dead
not ie < 11
not op_mini all
Despite that config, I still see some spread operators used in Nuxt built pages, like the following generated by nuxt:
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["pages/events/_slug.pages/index"],{
/***/ "./assets/svg/events/market.svg":
/*!**************************************!*\
!*** ./assets/svg/events/market.svg ***!
\**************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ({
functional: true,
render(_h, _vm) {
const { _c, _v, data, children = [] } = _vm;
const {
class: classNames,
staticClass,
style,
staticStyle,
attrs = {},
...rest
} = data;
I searched from some time across different issues about NuxtJS and Babel, but Nuxt claims that it works with IE9 without extra Babel configuration, which is not the case here. I'd like to understand why the code is not transpiled the right way.
I ran into a similar issue: A Nuxt app wouldn't work in the Edge browser because of spread operators in #nuxtjs/axios and bootstrap-vue. I did find a solution.
The build property in nuxt.config.js should be defined as follows:
build: {
babel: {
babelrc: true,
configFile: './babel.config.js'
},
transpile: [ '#nuxtjs/axios', 'bootstrap-vue' ],
// Other config
}
The transpile property is key here. Internally, Nuxt defines an exclude for babel-loader that ignores everything in node_modules, unless it's in transpile.
Using babel.config.js also appears to matter, and the official Babel documentation says you should use it if you want to process node_modules.
babel.config.js:
module.exports = function (api) {
api.cache(true);
return {
sourceType: 'unambiguous',
presets: ['#nuxt/babel-preset-app'],
plugins: ['#babel/plugin-proposal-object-rest-spread']
};
}
You don't need include or exclude here, as it's taken care of by Nuxt, as noted.

how to test if babel works and my plugins are executed

I'm using Next.js for Server Side Rendering of React application (with styled-components) and have issue with Babel plugins I'm using to show name of the components I'm using in code.
This is my .babelrc file:
{
"env": {
"development": {
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
},
"production": {
"presets": "next/babel",
"plugins": [
[
"babel-plugin-styled-components",
{
"displayName": false,
"ssr": true
}
]
]
},
"test": {
"presets": [
[
"env",
{
"modules": "commonjs"
}
],
"next/babel"
]
}
}
}
When I'm running cross-env NODE_ENV=development concurrently "tsc --watch" next
I'm getting these lines - meaning .babelrc is used during copilation:
[1] > Using external babel configuration
[1] > Location: "...../.babelrc"
[1] > Using "webpack" config function defined in next.config.js.
But once I go to dev tools and see some styled-component I can see this: class="sc-iyvyFf gGaJAt" but on my code I have this definition:
const Title = styled.div`
font-size: 40px;
line-height: 1.13;
`
As it seems from documentation example - I should get something like ... <button class="Button-asdf123 asdf123" /> instead of just <button class="asdf123" />. But I don't.
After going deeper I found this issue ( https://github.com/styled-components/styled-components/issues/1103#issuecomment-324302997 ) based on errors I get in browser console that said:
It seems that only the server code is being transpiled and not the client code 😉
So Question: How to test if babel works correctly and .babelrc is being used in all places?
P.S. In my case those classes that I've got on client side had this prefix sc- meaning in my head styled-components. So I was not sure if the plugin from .babelrc works at all or it works, but I haven't set any special property in declaration of styled-components thus get this general prefix sc-
UPDATE Here is my custom next.conf.js I'm using
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { ANALYZE } = process.env
const path = require('path')
module.exports = {
exportPathMap: function() {
return {
'/': { page: '/' }
}
},
webpack: function(config) {
if (ANALYZE) {
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerPort: 8888,
openAnalyzer: true
})
)
}
config.resolve.alias = {
'styled-components': path.resolve('./node_modules/styled-components/')
}
return config
}
}
Looks like no one has unfortunately answered this before;
What you're seeing probably comes down to this little piece of code you posted: tsc --watch
If you execute TypeScript transpilation before Babel and leave it up to TypeScript to transpile to ES5, it'll transpile all tagged template literals, not giving our plugin anything to hook onto.
Since you're already using next.js you won't need to set up your Babel pipeline from scratch. Rather you only need to disable this type of transpilation in TypeScript.
I'd suggest you to set target inside your tsconfig.json to ESNext so that it leaves everything up to Babel.
https://www.typescriptlang.org/docs/handbook/compiler-options.html (See "--target")

Uncaught TypeError: Cannot call a class as a function

I have looked through all of the answers on this question:
Getting "Cannot call a class as a function" in my React Project
I am still unable to work out why the below is returning the error 'Cannot call a class as a function'. Am I missing something here in terms of the syntax?
I am running through Gulp, Rollup and Babel
All plugins for above are included
The selector for reactDOM.render is fine and export of the class is not needed
Code:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div />
);
}
}
// Selector is fine, changes bg to red
document.querySelector('#app').style.background = 'red';
ReactDOM.render(<App />, document.querySelector('#app'));
Error:
Gulp task with Rollup and Babel:
gulp.task('js', () => {
// Package up ES6 moduleswith stream
const stream = plugins.rollupStream({
input: paths.dev + '/script/app.js',
sourcemap: true,
format: 'iife',
name: 'app',
plugins: [
plugins.rollupPluginReplace({'process.env.NODE_ENV': JSON.stringify( 'production' )}),
plugins.rollupPluginJsx({ factory: 'React.createElement' }),
plugins.rollupPluginCommonjs({}),
plugins.rollupPluginNodeResolve({ jsnext: true, main: true }),
plugins.rollupPluginIncludepaths({ paths: [paths.dev + '/script/'] })
]
})
return stream
.on('error', e => {
console.error(e.stack);
notifier.notify({
title: 'Rollup error',
message: e.stack
});
stream.emit('end');
})
// Error handling
.pipe(plugins.plumber())
// Prepare files for sourcemap
.pipe(plugins.vinylSourceStream('app.js', paths.dev + '/script/'))
.pipe(plugins.vinylBuffer())
.pipe(plugins.sourcemaps.init({ loadMaps: true }))
// Convert ES6
.pipe(plugins.babel({ presets: ['es2015', 'react'] }))
// Write sourcemap
.pipe(plugins.sourcemaps.write('.'))
.pipe(gulp.dest(paths.tmp + '/script/'))
.pipe(plugins.browserSync.stream());
});
Codebase:
https://github.com/alexplummer/framework-react/blob/master/_dev/script/app.js
The issue is that your JSX is not transpiled correctly. If you look at the output in the devtools (second error from the bottom in the stack trace), you'll see that the class is called as a regular function:
reactDom.render(App(), document.querySelector('#app'));
// ^^^^^
You are using rollup-plugin-jsx and it seems to handle that differently. There is really no reason to use this, if you are using Babel anyway, since Babel can transpile your JSX as well. I'd assume that you have added this, because Rollup was complaining about JSX. That's because your build pipeline is not quite right. You currently bundle the code with Rollup first, then you run Babel over it.
You can integrate Babel directly into Rollup with rollup-plugin-babel, so everything that is bundled by Rollup will automatically be transpiled by Babel. By adding this plugin you can remove rollup-plugin-jsx entirely and you also don't need to pipe it to Babel afterwards.
These are the changes to tasks/js.js (Stack Overflow doesn't have syntax highlighting for git diffs, but you can see the highlighted version in the Gist - tasks/js.js diff):
diff --git a/tasks/js.js b/tasks/js.js
index 0caabc1..7c5319d 100644
--- a/tasks/js.js
+++ b/tasks/js.js
## -70,7 +70,10 ## gulp.task('js', () => {
name: 'app',
plugins: [
plugins.rollupPluginReplace({'process.env.NODE_ENV': JSON.stringify( 'development' )}),
- plugins.rollupPluginJsx({ factory: 'React.createElement' }),
+ plugins.rollupPluginBabel({
+ exclude: 'node_modules/**',
+ presets: [['es2015', { modules: false }], 'react']
+ }),
plugins.rollupPluginCommonjs({}),
plugins.rollupPluginNodeResolve({ jsnext: true, main: true }),
plugins.rollupPluginIncludepaths({ paths: [paths.dev + '/script/'] })
## -93,8 +96,6 ## gulp.task('js', () => {
.pipe(plugins.vinylSourceStream('app.js', paths.dev + '/script/'))
.pipe(plugins.vinylBuffer())
.pipe(plugins.sourcemaps.init({ loadMaps: true }))
- // Convert ES6
- .pipe(plugins.babel({ presets: ['es2015', 'react'] }))
// Write sourcemap
.pipe(plugins.sourcemaps.write('.'))
.pipe(gulp.dest(paths.tmp + '/script/'))
Note that you need to turn off module transpilation in Babel, because Rollup needs ES modules. On a side note, babel-preset-es2015 is deprecated in favour of babel-preset-env, which contains everything that the es201x presets did and more. It is a drop-in replacement for es2015, for details see Migration guide from es2015 to env.

Browserify requires vendor module built with Browserify

I'm having problem with Browserify requiring a vendor library.
The vendor library I'm using is better-dom, which is also built with Browserify. I installed it from bower and when I'm trying to built, I got:
Error: Cannot find module './utils' from '<...>/bower_components/better-dom/dist'
Apparently Browserify is trying to parse and process the requires statements in the pre-built library. I tried browserify-shim and modulify with no luck, other attempts are also included below. Any help is appreciated, thanks in advance.
My configuration:
package.json:
...
"browser": {
"DOMLegacy": "./bower_components/better-dom/dist/better-dom-legacy.js",
"DOM": "./bower_components/better-dom/dist/better-dom.js"
},
...
Gulpfile.js:
gulp.task('scripts', function() {
var bundle = browserify({
noparse: ["<...>bower_components/better-dom/dist/better-dom.js"]
});
bundle.add('./js/all.js');
// bundle.external("./bower_components/better-dom/dist/better-dom-legacy.js");
// bundle.external("./bower_components/better-dom/dist/better-dom.js");
// bundle.transform({ modulify: {
// "./bower_components/better-dom/dist/better-dom-legacy.js": "DOMLegacy",
// "./bower_components/better-dom/dist/better-dom.js": "DOM"
// }});
// bundle.require(
// "./bower_components/better-dom/dist/better-dom-legacy.js",
// { expose: "DOMLegacy" });
// bundle.require(
// "./bower_components/better-dom/dist/better-dom.js",
// { expose: "DOM" }
// );
return bundle.bundle()
.on('error', function(e) {
console.log(e.toString());
this.emit('end');
})
.pipe(source('all.js'))
.pipe(gulp.dest(paths.assets));
});
I just found out there is a bug in browserify 5 with the noparse option.
Workaround: use the old name of this option: noParse (still working in browserify 5)
var bundle = browserify({
noParse: ["<...>bower_components/better-dom/dist/better-dom.js"]
});
It should fix your build.

Categories

Resources