I see lots of examples for react structured with var React = require('react') syntax. When I try and use this I get "require is not defined". How do I use and set up my static project to use require syntax?
Update
In actuality I am looking for a webpack/browserify config file so I can get started with React and CommonJS quickly. I have only written react apps without said build tools
require is not a React api, nor is it a native browser api (for now).
require comes from commonjs and is most famously implemented in node.js, if you have used node.js, you will see requires everywhere.
due to the popularity of require in node, people have built tools which will transform code that is written in nodejs style to be useable on the browser.
there's a few benefits to using require, it helps you keep your code modular and for some projects it allows you to write isomorphic code (code that runs both on client and server with minimal change)
In order to use require, you will need to use a tool such as webpack or browserify, I will use browserify as an example.
first create an 'index.js'
require('./app.js');
alert('index works');
then create an app.js
alert('app works');
next install the browserify cli
npm install -g browserify
And call this command in your shell
browserify index.js > bundle.js
Now you will have a bundle.js, in your html page create a
<script src="bundle.js"></script>
And you should see both alerts run
Now you can continue to code, you can add react in your code by doing a
npm install react --save
and then require it in app.js for example
var React = require('react');
React.createClass({
render: function(){/*Blah Blah Blah*/}
})
BTW,
If you are using webpack you can add to your webpack.config.js config file
The following lines, eliminating the need to use require statements in your files:
plugins: [
new webpack.ProvidePlugin({
'React': 'react',
'$': 'jquery',
'_': 'lodash',
'ReactDOM': 'react-dom',
'cssModule': 'react-css-modules',
'Promise': 'bluebird'
})
],
This is of course less verbose and not all developers like it, but it's good to know :)
Related
I was just wondering, I started using Webpack for a new project and so far it's working fine. I almost would say I like it better than Grunt, which I used before. But now I'm quite confused how and or I should use it with my Express back-end?
See, I'm creating one app with a front-end (ReactJS) and a back-end (ExpressJS). The app will be published on Heroku. Now it seems like I should use Webpack with ExpressJS as well to get the app up and running with one single command (front-end and back-end).
But the guy who wrote this blogpost http://jlongster.com/Backend-Apps-with-Webpack--Part-I seems to use Webpack for bundling all back-end js files together, which is in my opinion really not necessary. Why should I bundle my back-end files? I think I just want to run the back-end, watch my back-end files for changes and use the rest of Webpack's power just for the front-end.
How do you guys bundle the front-end but at the same time run the back-end nodejs part? Or is there any good reason to bundle back-end files with Webpack?
Why to use webpack on node backend
If we are talking about react and node app you can build isomorphic react app. And if you are using import ES6 Modules in react app on client side it's ok - they are bundled by webpack on the client side.
But the problem is on server when you are using the same react modules since node doesn't support ES6 Modules. You can use require('babel/register'); in node server side but it transipile code in runtime - it's not effective. The most common way to solve this problem is pack backend by webpack (you don't need all code to be transpile by webpack - only problematic, like react stuff in this example).
The same goes with JSX.
Bundling frontend and backend at the same time
Your webpack config can have to configs in array: one for frontend and second for backend:
webpack.config.js
const common = {
module: {
loaders: [ /* common loaders */ ]
},
plugins: [ /* common plugins */ ],
resolve: {
extensions: ['', '.js', '.jsx'] // common extensions
}
// other plugins, postcss config etc. common for frontend and backend
};
const frontend = {
entry: [
'frontend.js'
],
output: {
filename: 'frontend-output.js'
}
// other loaders, plugins etc. specific for frontend
};
const backend = {
entry: [
'backend.js'
],
output: {
filename: 'backend-output.js'
},
target: 'node',
externals: // specify for example node_modules to be not bundled
// other loaders, plugins etc. specific for backend
};
module.exports = [
Object.assign({} , common, frontend),
Object.assign({} , common, backend)
];
If you start this config with webpack --watch it will in parallel build your two files. When you edit frontend specific code only frontend-output.js will be generated, the same is for backend-output.js. The best part is when you edit isomorphic react part - webpack will build both files at once.
You can find in this tutorial explanation when to use webpack for node (in chapter 4).
This is my second update to this answer, which is beyond outdated by now.
If you need full a stack web framework in 2023, I'd recommend nextjs (which is built on top of react). No need to go around setting up anything, it just works out of the box, and is full stack.
On the other hand, if you need to compile your nodejs project written in typescript (which you should use as much as you can for js projects), I would use tsup-node.
You don't need to be a genius to imagine that in 3-5 years I'll come back to this and say this is really outdated, welcome to javascript.
This answer is outdated by now since node now has better support for ES modules
There's only a couple of aspects I can redeem the need to use webpack for backend code.
ES modules (import)
import has only experimental support in node (at least since node 8 up to 15). But you don't need to use webpack for them work in node.
Just use esm which is very lightweight and has no build step.
Linting
Just use eslint, no need to use webpack.
Hot reloading/restart
You can use nodemon for this. It's not hot reloading but I think it's way easier to deal with.
I wished I could refer to a more lightweight project than nodemon, but it does do the trick.
The blog post you shared (which is dated by now) uses webpack for having hot reloading. I think that's an overkill, opens a can of worms because now you have to deal with webpack config issues and hot reloading can also lead to unexpected behaviour.
The benefits we get from using tools like webpack on the frontend don't really translate to backend.
The other reasons why we bundle files in frontend is so browsers can download them in an optimal way, in optimal chunks, with cache busting, minified. There's no need for any of these in the backend.
Old (and terrible, but maybe useful) answer
You can use webpack-node-externals, from the readme:
npm install webpack-node-externals --save-dev
In your webpack.config.js:
var nodeExternals = require('webpack-node-externals');
module.exports = {
...
target: 'node', // in order to ignore built-in modules like path, fs, etc.
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
...
};
to use Webpack for bundling all back-end js files together, which is in my opinion really not necessary.
I think you are absolutely right. It's not necessary at all. I've been researching on this topic for a while. I've asked lots of questions on this topic, and up to this day, I haven't found yet a single "real" reason for one to use webpack on a Node.js back-end.
I'm not saying you can't or shouldn't set up a webpack-dev-server to develop your back-end code locally. But you definitely don't need to bundle your backend code on your build process.
webpack bundles are meant for the browser. Take a look at its official docs: Why webpack?. Historically, browsers never had a built-in module system, that's the reason why you need webpack. It basically implements a module system on the browser. On the other hand, Node.js has a built-it module system out of the box.
And I do re-use all of my front-end code for SSR on my server. The very same front-end files are run on my server as-is without any bundling (they are just transpiled, but the folder structured and number of files is the same). Of course I bundle it to run on the browser, but that's all.
To run on your Node.js server, simply transpile it with babel, without webpack.
Just use ["#babel/preset-env", { targets: { node: "12" }}], on your babel config. Choose the Node version of your backend environment.
backend
dist_app // BABEL TRANSPILED CODE FROM frontend/src
dist_service // BABEL TRANSPILED CODE FROM backend/src
src
index.tsx
frontend
src
App.tsx
public // WEBPACK BUNDLED CODE FROM frontend/src
You can perfectly render your frontend code on the server, by doing:
backend/src/index.tsx
import { renderToString } from "react-dom/server";
import App from "../dist_app/App";
const html = renderToString(<App/>);
This would be considered isomorphic, I guess.
If you use path aliases on your code, you should use babel-plugin-module-resolver.
So I'm working with JS on the frontend, building something for a client. Details aren't super important except that I do not have access to node.
I'm using unpkg to include various NPM packages in the browser (like React/ReactDOM/Babel for instance). These packages have a UMD build so they work out of the box.
However, there are a few packages I'd like to use that do not have a UMD build (namely react-dates or react-datepicker). I've tried serving different files via unpkg and referencing the exported modules. Since they don't have UMD builds, I'll either get an error module is not defined which makes sense, or that the module I'm referencing DatePicker is not defined.
So I thought maybe I could build a single file with browserify but I've never used it before and any docs I could find are lacking. Heres what I did
var DatePicker = require("react-dates");
In a file called test.js and then:
browserify test.js -o bundle.js
Output that, upload it to the client assets, reference it like:
<script src="/js/bundle.js"></script>
But var DatePicker = require("DatePicker") throws error require is not defined (I thought that was the point of browserify?) and console.log(DatePicker) throws is not defined as well.
At this point I'm at a loss. I'm being stubborn but I really really just want to use a react datepicker and avoid adding jQuery to this project for the sole purpose of a datepicker. As far as I can tell unpkg is not an option but I feel like browserify could work and I'm just doing something wrong.
Any help is greatly appreciated!
You don't have to do this, you can find the needed files in the dist folder (New folder\node_modules\react-datepicker) after you "npm install react-datepicker" within a folder, but be sure you have a package file into that, otherwise the install won't work.
The files should look like this
EDIT:
The requirejs code that you need is
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.min.js"></script>
<script>
requirejs.config({
paths: {
'react': 'https://unpkg.com/react#15.3.2/dist/react',
'react-dom': 'https://unpkg.com/react-dom#15.3.2/dist/react-dom',
'prop-types': 'https://unpkg.com/prop-types#15.6.0/prop-types',
'react-onclickoutside': 'https://unpkg.com/react-onclickoutside#6.7.0/dist/react-onclickoutside',
'react-popper': 'https://unpkg.com/react-popper#0.7.4/dist/react-popper',
'moment': 'https://unpkg.com/moment#2.19.3/moment',
'datepicker': 'https://unpkg.com/react-datepicker#0.61.0/dist/react-datepicker'
}
});
requirejs(['react', 'react-dom', 'prop-types', 'react-onclickoutside', 'react-popper', 'moment', 'datepicker'], function(React, ReactDOM, PropTypes, onClickOutside, Popper, moment, DatePicker) {
ReactDOM.render(
React.createElement('p', {}, 'Hello, World!'),
document.getElementById('root')
)
});
but as far as I got, datepicker requested for "module" which is not defined, this can be the same problem as here. I will investigate more about this issue.
I have a legacy project which uses Gulp to compile SASS and minify JS etc. (based on Drupal).
I'd like to use ES6 style imports and also be able to import modules that are located in node_modules without referencing the full path (for example import the lodash.debounce module as
import throttle from 'lodash.throttle'
What do I need to achieve that? (besides Gulp and NPM). Babel? Browserify? Lost with all the tooling.
I'd like to avoid webpack as it would increase the complexity of my project (and I don't know if I can use it in parallel with the way Drupal 7 is doing things)
Yep, you want babel. The documentation to set it up in your gulpfile is here: http://babeljs.io/docs/setup/#installation
You'll want to use the es2015 preset to enable the import syntax.
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("default", function () {
return gulp.src("src/app.js")
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest("dist"));
});
To use import you need a transpiler, for example babel.
Assuming you are building code for the browser then to use import (transpiled to require) you need webpack or browserify which will also allow you to import from node_modules (there are other module builders too, jspm and systemjs, however I know next-to-nothing about them).
For either of these you will also need something to enable babel to be used in the build process. I use webpack with babel-loader.
I found a useful reference here specifically on using ES6 modules with webpack.
I'm working on an application that needs to pull in the ReadiumJS library, which uses AMD modules. The app itself is written in es6 w/ webpack and babel. I've gotten the vendor bundle working correctly, and it's pulling in the built Readium file, but when I try to require any of the modules Webpack says it can't resolve them. Anyone ever do this before with Webpack and RequireJS? Here's some info that may help - not sure what else to include as this is my first time really using Webpack..
Folder Structure
/readium-src
/readium-js
/ *** all readium-specific files and build output (have to pull down repo and build locally)
/node_modules
/src
/app.js -> main entry for my app
/webpack.config.babel.js
webpack.config.js entries
entry: {
vendorJs: [
'jquery',
'angular',
'../readium-src/readium-js/build-output/_single-bundle/readium-js_all.js',
'bootstrap/js/alert.js' //bootstrap js example
],
appJs: './app.js'
}
Trying to require it in app.js
var readiumSharedGlobals = require('readium_shared_js/globals');
I never really got into using RequireJS, so really struggling to understand how to consume that type of module along side other types of modules with webpack. Any help greatly appreciated :)
Update
If I change my app.js to use this instead:
window.rqReadium = require('../readium-src/readium-js/build-output/_single-bundle/readium-js_all.js');
Then it appears to try to load all the modules, but I get a strange error:
Uncaught Error: No IPv6
At this point, I'm unsure of
Should I have to require the entire path like that?
Is this error something from webpack, requirejs, or Readium? Tried debugging, but couldn't find anything useful...
UPDATE 8/12/2016
I think this is related to an issue with a library that Readium is depending on: https://github.com/medialize/URI.js/issues/118
However, I'm still not clear on how to correctly import AMD modules with webpack. Here's what I mean:
Let's say I have an amd module defined in moneyService.amd.js like this:
define('myMoneyService', ['jquery'], function($) {
//contrived simple example...
return function getDollaz() { console.log('$$$'); }
});
Then, in a sibling file, app.js, I want to pull in that file.
//this works
var getDollaz = require('./moneyService.amd.js');
//this works
require(['./moneyService.amd.js'], function(getDollaz) { getDollaz(); }
//this does not
require(['myMoneyService' /*require by its ID vs file name*/], function(getDollaz) {
getDollaz();
}
So, if we cannot require named modules, how would we work with a third party lib's dist file that has all the modules bundled into a single file?
Ok, so there's a repo out there for an Electron ePub reader using Readium, and it's using webpack: https://github.com/clebeaupin/readium-electron This shows a great way to handle pulling in RequireJS modules with webpack.
One super awesome thing I found is that you can specify output.library and output.libraryTarget and webpack will transpose from one module format to another... freaking awesome! So, I can import the requirejs module, set output library and libraryTarget to 'readium-js' and 'commonjs2' respectively, then inside my application code I can do import Readium from 'readium-js';
I'm trying to build a react application using rollup instead of browserify and babel. I realize I need to use the rollup-plugin-babel to transpile jsx, but when I tell rollup the format is iife, the final page loads with an error:
Uncaught ReferenceError: React is not defined
What do I need to add to the rollup.config.js to include the node modules I've installed in package.json in my final build?
Two options:
Include React as a separate <script> tag before your app bundle
Include rollup-plugin-node-resolve in your config file, to pull in dependencies from your node_modules folder.
If you take the second route you'll also need rollup-plugin-commonjs (to convert the CommonJS module into an ES module). I think you would also need to add import * as React from 'react' to each module that contained JSX, otherwise you'll continue to get the ReferenceError.
Note: you might be able to use rollup-plugin-buble to transpile JSX. It's similar to the Babel plugin but much faster (though it doesn't transpile every ES2015 feature)