Compile/transpile code while developing React app - javascript

I am developing an app in React.
Until now I have just included
<script src='//unpkg.com/react#15/dist/react.min.js'>
<script src='//unpkg.com/react-dom#15/dist/react-dom.min.js'>
<script src='//unpkg.com/babel-standalone#6/babel.min.js'>
and then I neither had to use
import React from 'react';
import ReactDOM from 'react-dom';
since everything was loaded nor had to compile anything since babel compiled it in real-time.
However, when I want to include third-party libraries installed with npm, it seems I have to use import. For instance, if I install react-dates with npm-install react-dates --save and want to include it with
import { DateRangePicker, SingleDatePicker, DayPickerRangeController } from 'react-dates';
I get the error
Uncaught ReferenceError: require is not defined
I guess it's because I don't use RequireJS, Webpack, Gulp or anything.
What is the preferred way to be able to include components while developing, so I don't have to compile my code everytime I did a small change?

You can use webpack to configure your code, and run it in watch mode or use
webpack-dev-server during development so, that will allow you to compile your code automatically any time you do a small change
Your webpack.config.js should look something like
var debug=process.env.NODE_ENV !== "production";
var path=require("path");
var webpack=require("webpack");
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/index.js",
module: {
rules: [{
test: /\.jsx?$/,
exclude: [/node_modules/],
use: [{
loader: "babel-loader",
options: {presets: ["stage-0","es2015","react"]}
}]
}]
},
output: {
path: __dirname + "/src",
filename: "bundle.js"
},
plugins: debug? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({mangle: false, sourcemap: false})
]
}
And in your package.json, you can define scripts
"scripts": {
"start": "webpack-dev-server --content-base src",
"build": "webpack --watch"
}
If you run a npm run build command webpack will start in watch mode and you won't need to recompile your code again and again.
or you can run npm start for using webpack-dev-server in development mode.
See how to set up webpack here

Related

Relative references must start with either "/", "./", or "../"

I am newbie to lit-element, and when use import to include the library, I am getting error as:
Uncaught TypeError: Failed to resolve module specifier "lit-element".
Relative references must start with either "/", "./", or "../".
Please provide any alternatives/solutions.
import { LitElement, html } from 'lit-element';
class MyElement extends LitElement {
render(){
return html`
<div>
<p>A paragraph</p>
</div>
`;
}
}
customElements.define('my-element', MyElement);
This doesn't work because js imports must reference a specific file with either a relative path or an absolute path, assuming your project structure is something like the following:
/node_modules
/lit-element
/other-library
/src
/components
my-element.js
index.html
From my-element.js, your import would be
import {LitElement, html} from '../../node_modules/lit-element/lit-element.js'
However, since this kind of configuration is confusing and you'll probably end up setting a build script sometime too, the recommendation would be to keep your imports as they are right now and use a dev server that remaps your imports to node_modules like open-wc's web server
Update (Feb. 2021): The web server mentioned on this question has gone through a few iterations and improvements. The current package is #web/dev-server
As you probably know, this type of import is known as 'bare import':
import { LitElement, html } from 'lit-element';
And the error happens because web browsers cannot resolve bare imports by themselves.
I don't know what webserver are you using for developing, but a good way of avoid this type of warnings is choose one that could manage this type of imports, for example web-dev-server
There are other approaches, using, for example tools like Webpack, Polymer-cli, Open Web Components, etc, as this article explains, but, IMO, the web-dev-server option is a very good one for start.
I tried webpack for this issue and that works fine for me.
Here is how I set up webpack on my node javascript project.
First, you need to install the following packages on your project
npm install --save-dev webpack
npm install --save-dev html-webpack-plugin
npm install --save-dev css-loader
npm install --save-dev style-loader
Then, you have to create webpack.config.cjs on your project root and paste the following code into it. (please change file paths as your file structure)
const path = require('path');
const HtmlWebpack = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
},
plugins:[
new HtmlWebpack({
template:path.resolve(__dirname,'./src/template/index.html')
})
],
module:{
rules:[
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource"
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
]
},
devServer:{
port:8080,
hot: true,
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true,
client: {
progress: true,
},
}
}
then add this line to your package.json file
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server --open",
},
now open a terminal on your project root and run npm run dev on it.
You can serve bare module imports with polimer-cli.
a. install it: npm install --save-dev polymer-cli
b. Create polymer.json in your project with roughly contens:
{
"entrypoint": "index.html",
"shell": "app.js",
"npm": true
}
c. do polymer serve

Using local npm libraries with es6, babel, and webpack

I'm running into an issue that appears to be due to my lack of understanding with webpack. I have created a file structure that looks like this:
|-serverless-cloud-functions
||-my-local-libs
|||-twilioClient
||-service1
||-service2
twilioClient is a library that I made, that needs to be included in service1 and service2. Because of limitations with the serverless framework, you can not bundle files outside of the service, so the only option (I think) is to use a npm install ../my-local-libs/twilioClient from inside a service folder. This works for installing the module, but now it resides in node_modules. Currently, I am using webpack and babel as well.
I believe my root issue is that my webpack config looks like this:
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
module.exports = {
entry: slsw.lib.entries,
target: "node",
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
}
]
}
};
Which excludes my es6 twilioClient lib, because it is in the node_modules folder.
I saw a couple people suggest that this was the way to accomplish 'exclude everything in node modules besides twilioClient':
module.exports = {
entry: slsw.lib.entries,
target: "node",
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules\/(?!(twilioClient))/
}
]
}
};
But this did not work in my case. Any help is greatly appreciated.
Instead of trying to exclude twilioClient, you could use Babel to compile it separately. Something like this (in the twilioClient directory):
npx babel src --out-dir lib
In twilioClient/package.json, you could then set main to lib/index.js instead of src/index.js so that importing scripts will get the compiled version:
"main": "lib/index.js",
Then instead of hosting twilioClient alongside service1 and service2, you could just push it to github, and install it in each client using npm:
npm install --save http://github.com/your_github_username/twilioclient.git
Now you can use twilioClient as if it were any other npm dependency.
I have encountered a similar problem of using local common package with babel.
If you would like to not change the main since you also actively edit the package and do not want to run the build each time you make a change, then you should use the below babel.config.js
module.exports = function(api) {
api.cache(true);
const plugins = [
'#babel/plugin-transform-modules-commonjs',
];
return {
plugins,
ignore: [
/node_modules\/(?!(your-pkg)\/)/,
],
};
};
This transpiles the code for your-pkg into node_modules dir in dist.

webpack-dev-server does not reload and build automatically - configuration issue

I am using in my project:
"webpack": "2.2.1",
"webpack-dev-server": "2.4.2"
and I need to build an application when a file change using webpack-dev-server live reloading.
In my package.json I have this setup:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --hot --inline"
},
Currently I am able to build the application manually by running:
webpack and I am able to initialize the developer server using npm start.
The problem I am facing is that after npm start and local server runs, if I make some changes in JS files the application is NOT being rebuilded and page is not refreshed automatically. Currently I need to rerun webpack manually all the time in console.
I receive no errors in console, so I suppose is a wrong configuration issue.
Could you please point me out what is wrong in my settings?
// file: webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js',
},
devServer: {
inline: true,
port: 8080
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
};
webpack-dev-server serves the files from memory.
From readme:
It uses webpack-dev-middleware under the hood, which provides fast in-memory access to the webpack assets.
So it does not write any file to disk and it also works without the files being present on your file system. When you delete the build directory and start the dev server without running webpack before, it should still work. If it doesn't, you don't hit the paths that are served from the dev server and instead are using the files from the file system.
The index.html you're using is probably outside the build directory and therefore you include the bundle like this:
<script src="build/app.bundle.js"></script>
You're requesting /build/app.bundle.js on the server, but webpack-dev-server will only serve /app.bundle.js (because that's the filename you configured). To solve this issue you can configure output.publicPath:
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js',
publicPath: '/build/'
},
This will affect loaders that include assets. If you don't want that, you can set devServer.publicPath instead, but it's recommended to keep them the same.

React webpack / browserify "unexpected token"

I have this npm module that I created and every time I try to include it to see if it works I get this error:
Unexpected token <
You may need an appropriate loader to handle this file type.
I've used react-starterkit and included it in main.js like so
var ReactDOM = require('react-dom');
var ColorPicker = require('color-picker-react');
ReactDOM.render(<ColorPicker />, document.getElementById('app'));
then when i run gulp which runs webpack I get the error. Here's the webpack.config.js
module.exports.getConfig = function(type) {
var isDev = type === 'development';
var config = {
entry: './app/scripts/main.js',
output: {
path: __dirname,
filename: 'main.js'
},
debug : isDev,
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}]
}
};
if(isDev){
config.devtool = 'eval';
}
return config;
}
I've tried everything I could think of and still can't get it to work. I'm not using ES6 anywhere and I've tried many different react starter kits but I just can't get it to work. Please help!!!
P.S. I am able to get the project to run when I clone it locally and build out app.js with browserify like so: browserify -t [ babelify --presets [ react ] ] app.js -o bundle.js
To solve the problem you need to remove the line exclude: /node_modules/ if you are not the author of the npm module (But you should go with another module).
The component color-picker-react doesn't seem to have a release build or script that compile the jsx. So you need to do it by your own and compile the jsx file on the fly using wepack.
Instead of just removing the exclude: /node_modules/
You can exclude all /node_modules/ except the /node_modules/color-picker-react folder by using a regex pattern :
//will exclude all modules except `color-picker-react`
exclude: /node_modules\/(?!color-picker-react).*\//,
EDIT Basics for creating a npm module:
A correct setup for a npm module is to add a prepublish script to
ensure compilation happens automatically before uploading to NPM.
Thus when you push your module to npm the users doesn't need to compile the module they can just require it.
Taking an example of a node_module:
https://github.com/securingsincity/react-ace/blob/master/package.json
The package.json file is saying which file is the entry point when you required the module
"main": "lib/ace.js",
You can see in the github repository that the lib folder doesn't exist because added to the .gitignore but the line
"prepublish": "npm run clean && npm run build"
is run before uploading to NPM so on the npm repository the lib/ folder exist and you can see it when you do npm install --save react-ace the lib folder appears in the node_modules/react-ace/ folder
A great link that explains how to build npm modules in es6 for example http://javascriptplayground.com/blog/2015/10/authoring-modules-in-es6/
EDIT explain what needs to be done on react-color-picker module :
Sorry i didn't see that you was the author of the module so you should go with the solution below.
The react-color-picker for example doesn't have a prepublish script and the main file is index.js which is
var ColorPicker = require('./colorpicker.js'); // require a file with jsx will throw an error if not precompiled
module.exports = ColorPicker;
So a syntax error is thrown.
To be able to use the npm module in your other applications :
Create a webpack config for the npm module to handle the conversion of your react component written using jsx (you can take some of the webpack configs of this module https://github.com/securingsincity/react-ace set libraryTarget: 'umd' you module will be more easy to consume from various module systems (global, AMD, CommonJS).)
add a prepublish script that output a precompiled version of the color picker (lib/pickedprecompiled.js)
change the main to "main": "lib/pickedprecompiled.js",

"ReferenceError: Can't find variable: require" (using babel.js output) [duplicate]

When this code (generated from babel) runs I get an error exports is undefined
Object.defineProperty(exports, '__esModule', {
any ideas?
You are most likely not executing the code in an environment that supports CommonJS modules. You could use a bundler, such as Browserify or webpack
to bundle your modules into something that can be run in different environments.
Or you could choose a different module transformer.
With webpack
Run npm install -g webpack; npm install -D babel-loader. Then with this webpack configuration:
// webpack.config.js
module.exports = {
entry: "./path/to/entry/module.js",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}
]
}
};
running the webpack command will convert all *.js files reachable via the entry file with babel and bundle them together into bundle.js.
I read an article about how ES6 import and export are only supposed to work in browser with "statically analyzable files" and Babel removed import and export support in the browser because of this. Something to do with async or possibly security?
If you want to skip the server-side bundling for dev purposes, you can put
window.MyModule = MyModule at the bottom, then import
var MyModule = window.MyModule at the top of your next file

Categories

Resources