webpack: how to transpile code in node_modules - javascript

I want to import nano-memoize in my web application that uses Typescript and Webpack to transpile to ES5.
npm install nano-memoize
add import 'nano-memoize/browser/nano-memoize' to the source file.
These steps do not work in IE 11. The page simply doesn't load.
On inspecting the code for nano-memoize/browser/nano-memoize.js in IE 11 developer console, I noticed it uses arrow function. If I copy nano-memoize/browser/nano-memoize.js directly to my source folder, they get transpiled to ES5 and everything works in IE 11 too.
So why is nano-memoize/browser/nano-memoize.js not getting transpiled?
Build setup:
webpack : ^4.40.2,
#babel/core : ^7.4.0,
awesome-typescript-loader : ^5.2.1,
UPDATE:
This was a webpack configuration issue where the node_modules are excluded from compilation. The skeleton setup is created by a script and my bad I never check this. The following in webpack.config.js for babel-loader can selectively compile the required node_modules. Replace with required module name.
{
test: /\.js$/,
exclude: function(modulePath) {
return /node_modules/.test(modulePath) &&
!/node_modules\/<MY_MODULE>/.test(modulePath);
}
}

Try it by using polyfills in your project , Below is the script tag to import in your index.html file
<script src="https://cdn.polyfill.io/v3/polyfill.min.js"></script>

Related

Vue JS note transpiling node module

I have a Vue app created with vue create app and have the following settings in the babel.config file:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
My Vue config file also looks like this:
module.exports = {
configureWebpack: {
optimization: {
splitChunks: false
}
},
css: {
extract: false,
}
}
At the moment when I run vue-cli-service build it compiles all my modules and styles into 1 bundled JS file.
There is an issue however with one of my NPM modules: socket.io-client
It appears that the way that Vue is compiling my app, it is not transpiling something within this package which is causing syntax errors in Internet Explorer 11.
I am fairly sure the problematic code in socket.io-client lies with one of it's dependencies called debug.
What I would like to do is have this package (socket.io-client) also transpiled so that I don't get the error in IE11.
I would have thought that Vue CLI would do this out of the box when you run the build but perhaps something has been setup wrong in my babel or Vue configuration? How could I resolve this issue?
Thanks!
You can use transpileDependencies option in your vue.config.js.
By default babel-loader ignores all files inside node_modules. If you want to explicitly transpile a dependency with Babel, you can list it in this option.
Example:
module.exports = {
...
transpileDependencies: [
'socket.io-client'
]
}
Found the issue here:
https://github.com/socketio/socket.io-client/issues/1328
Reverting the problematic package to previous version fixed it

How to make Webpack use project's "node_modules" in js scripts located outside the project folder?

I have Node.js project and the following structure of folders:
lib
awesome-formatter.js
FrontEndApp
prettify.js
node_modules
awesome-parser
BackEndApp
...
I use awesome-parser module and awesome-formatter.js library in prettify.js script like this:
require('awesome-parser')
require('../lib/awesome-formatter.js')
awesome-formatter.js, in turns, should use awesome-parser too:
require('awesome-parser')
My FrontEndApp has been configured to use Webpack, and I'm trying to run it in dev mode using npm run dev command. However, I got the following error:
ERROR Failed to compile with 1 errors
These dependencies were not found:
* awesome-parser in /home/user/dev/lib/awesome-formatter.js
I don't want to move awesome-formatter.js inside the FrontEndApp because I also use it in BackEndApp project (and probably in some other projects) and I don't want to create separate "node_modules" in "lib" for it just not to duplicate installed modules on disk.
So, my question is, how to make Webpack use project's "node_modules" in js scripts located outside the project folder?
P.S. Of course there are workarounds like symlinks or making a full-featured module (with package.json etc.) from lib/awesome-fromatter and installing it into FrontEndApp/node_modules, but is there a direct way to solve this problem?
I've found a solution: resolve.modules sould be added to Webpack configuration file.
module.exports = {
...
resolve: {
...
modules: [
'node_modules',
resolve('node_modules')
]
},
...
}
This means that Webpack is searching modules in 'node_modules' as a relative subfolder (and it's the usual behavior), and at the absolute path to the project's 'node_modules' as well: resolve('node_modules'), so that scripts in folders outside the project (like lib in my structure) can find and use it.

meteor-client-bundler with webpack __meteor_runtime_config__ is not defined

I am trying to use this with my webpack project
https://blog.meteor.com/leverage-the-power-of-meteor-with-any-client-side-framework-bfb909141008
but I get this error
ReferenceError: __meteor_runtime_config__ is not defined
Here are the steps I did
create a new meteor project
then I run the client bundler like this
meteor-client bundle —source=./ —destination=./meteor-client.bundle.js —config=meteor-client.config.json
and here is the config
{
"runtime": {
"DDP_DEFAULT_CONNECTION_URL": "http://localhost:3000"
},
"import": [
"meteor-base#1.3.0",
"mongo#1.4.2",
"reactive-var#1.0.11",
"jquery#1.11.10",
"tracker#1.1.3",
"shell-server#0.3.1",
"react-meteor-data"
]
}
then I copy my meteor-client.js to my webpack project node_modules
and import it like this
import 'meteor-client'
then I bundle webpack and run dev-server and I get the above mentioned error.
I had the same issue, and fixed that by putting my meteor-client.js to node_modules and exclude node_modules from processing by babel-loader with webpack (or you could just exclude meteor-client.js). Raw loading will workaround that.
In case someone still searching.

Why adding babel-loader in webpack conf file?

I am new to webpack and have seen some examples as following:
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
// ....
Why is this necessary since webpack auto transpiles es6 to es5?
Edit:
Ok, it DOES NOT transpile automatically unless instructed to do so.
Why is this necessary since webpack auto transpiles es6 to es5?
Webpack does not auto-transpile ES6 to ES5. It is simply a build tool. It does nothing but execute the plugins & loaders you tell it to.
But the es6 code I wrote get transpiled to es5 even without this "babel" rule
I don't see it transpiling ES6 to ES5.
The first example I looked for in your code was the conversion of let to var in the bundled code since this is probably the most commonly used ES6 feature.
With babel-loader, let gets converted to var (and some other fancy maneuvering). Without, it remains let.
To explore this, I commented out UglifyJS so the bundle was readable and ctrl+fed the file. You should be able to see this same behavior.
If you're expecting import to be converted to require, this won't happen as webpack just reads the file and loads it into the bundle. So, no require & no import appear in the bundle. This isn't transpilation, though. It's just a function of how webpack's bundling process works (searching for & injecting dependencies into the bundle).
Bonus points:
I would recommend adding your dist directory to .gitignore. Typically, you don't want your bundled code version controlled. You should rely on your build tools to handle this (you can add webpack to your package.json's postinstall if you want to simplify the installation for consumers of your project).
In hindsight, I realize you probably only added the dist directory because I asked to see the bundled code. Sorry! :p But I'll leave this here in case it helps someone else in the future.

Automatic script conversion js to jsx in react app

I'm new to REACT so be patient if I confuse terms.
The following html document starts an react app:
index.html
<html>
<head>
<script data-require="react#*" data-semver="15.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.0/react.min.js"></script>
<script data-require="react#*" data-semver="15.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.0/react-dom.min.js"></script>
<script data-require="redux#*" data-semver="3.2.1" src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.2.1/redux.js"></script>
<script data-require="react-redux#*" data-semver="4.4.5" src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js"></script>
<title>Hello world</title>
</head>
<body>
<h1>Share a sport activity</h1>
<div id="appMount"></div>
<script src="app.js"></script>
</body>
</html>
In the same folder as this index.html on the server there is an app.jsx file but no app.js file (see the src attribute of the script tag).
app.jsx
class Communicator extends React.Component {
constructor(props) {
super(props);
this.state = {message: this.props.message};
}
resetComm() {
this.setState({message: ''});
}
(...)
Magically, the index.html document sources the app.jsx file anyway. If I look at dev tools what has been delivered for the app.js file the ouput starts with
'use strict';
var _createClass = function () { function definePr...
which is not the content of the actual app.jsx. So, there is some server-side compiling involved.
So, I understand that the app.jsx file needs pre-compiling to js. I think (after some investigation) this server-side tranlation is done by babeljs and done on-the-fly.
The problem
If I run the index.html locally it gives me errors in the console that (of course) app.js is not found.
Question
How can I make my localhost environment (WAMP) behave like the server (it is the online editor platform plunkr.co). I have npm installed. I want it on-the-fly, even if that's slow and not recommended for production.
Everything that I find involves at least the setting of a proper script type
<script type="text/babel" src="app.js"></script>
but I would like to reproduce the exact same behavior of the server. Basically, I want the index.html (which seems to me a proper standalone app as it works on the server) to run on my local server. I think there is some babeljs setup required which I don't seem to understand.
Edit
By the way. The example was in a plunker at http://plnkr.co/
Edit 2
If I add babel.min.js to the header and add a .babelrc as suggested by #Eric it doesn't find the app.js still. If I source app.jsx it finds it but sources it as is. Also, the react app doesn't start.
Without knowing the rest of your project setup, I can't tell how the current app.js file is getting created, but you're right: what you need is to transpile the code via Babel. This can be done two ways in development: on the dev server (recommended), or in the dev browser using standalone Babel.
On the Dev Server (Recommended)
React's recommended way to start with React is using a tool called Create React App. Since you said you're new to React, this will take care of Babel behind the scenes and give you a development server (so you don't need WAMP, only Node and NPM), and a build process to create the assets like app.js to deliver to the production server.
If you don't have time to immediately learn Babel and Webpack, I'd recommend using Create React App first.
In the Dev Browser
If you don't want to introduce a new tool, and you just want to transpile JSX with minimal configuration, you can do this in the browser via the instructions. This used to be demonstrated in the React.js tutorials until they switched to recommending Create React App. The instructions for installing "in the browser" require two things: adding babel.min.js to your <head>, and adding the type="text/babel" attribute to your .jsx file (working code example below). However, the documentation gives this advice:
Compiling in the browser has a fairly limited use case, so if you are
working on a production site you should be precompiling your scripts
server-side. See setup build systems for more information.
Your HTML and JavaScript should look as follows (I've omitted a lot of your code for brevity):
index.html
<!doctype html>
<head>
<script src=src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.0/react-dom.js"></script>
</head>
<body>
<h1>Browser in JSX Demo</h1>
<div id="appRoot">If you're seeing this, it's not working.</div>
<script type="text/babel" src="app.jsx"></script>
</body>
</html>
app.jsx
class App extends React.Component {
render() {
return <div>It works!</div>;
}
}
const el = document.getElementById('appRoot');
ReactDOM.render(<App />, el);
Please note that the extensions used in the script src attribute and the JavaScript file must match. You can use .jsx or .js, but they must match. I don't know how your server is working its magic, but that's beyond the scope of the question, and is not expected behavior by default.
You can use Webpack to achieve what you want.
You can download every dependencies like this (if you have npm installed):
npm install --save-dev webpack
npm install --save-dev webpack-dev-server
npm install --save-dev loader-utils html-webpack-plugin extract-text-webpack-plugin
npm install --save-dev babel-core babel-loader babel-register
npm install --save-dev babel-preset-es2015 babel-preset-react
Then you can create the file webpack.config.js at the root of your folder with this code inside:
import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
export default () => ({
entry: [
path.join(__dirname, 'src/index.jsx'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
}),
]
module: {
rules: [
{
test: /.jsx?$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
use: [
{
loader: 'babel',
options: {
babelrc: false,
presets: [
['es2015', { modules: false }],
'react',
],
}
}
]
},
]
},
});
And in your package.json, add those lines:
{
...
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack"
}
...
}
You will now be able to run npm run dev for development and npm run build to compile the code ready for a production server.
You can init npm in your project if it's not already done like this npm init
You can also follow this guide: Setting Up A React Workflow with Babel and Webpack 2
Webpack is basically a tool that takes every .jsx file and convert it to a .js file. In the code above, I use index.jsx as the main file. Every react component that will be imported in this file will be automatically computed.

Categories

Resources