make a dir hello and run npm init inside it
add .gitignore file to exclude node_modules
install the following packages with -D flag (dev dependencies):
babel: @babel/core @babel/preset-env @babel/preset-react
webpack: webpack webpack-cli webpack-dev-server webpack-node-externals html-webpack-plugin node-sass
loaders: css-loader babel-loader sass-loader style-loader url-loader
react: react react-dom
{
"name": "hello",
"version": "1.0.0",
"description": "",
"main": "dist/main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --config webpack.dev.config.js",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.14.3",
"@babel/preset-env": "^7.14.2",
"@babel/preset-react": "^7.13.13",
"babel-loader": "^8.2.2",
"css-loader": "^5.2.5",
"html-webpack-plugin": "^5.3.1",
"node-sass": "^6.0.0",
"sass-loader": "^11.1.1",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"webpack": "^5.37.1",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2",
"webpack-node-externals": "^3.0.0"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
{
"presets": [
["@babel/preset-env", {
"targets": {
"node": "10"
}
}],
"@babel/preset-react"
]
}
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
devtool : 'inline-source-map',
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
options: { injectType: 'singletonStyleTag' }
},
"css-loader",
"sass-loader"
]
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'url-loader',
},
]
},
devServer: {
port: 5001
}
};
Here entry is src/index which imports the components and renders them in html root div.
HtmlWebpackPlugin is used to inject scripts and styles inside index.html
babel loader for transforming new es syntax to old compatible code.
style loaders - they work in reverse order. sass-loader to transform scss into css. Then css-loader to load css styles. And then style-loader to put those styles into style tags. You can skip the options in style-loader.
url-loader for putting images into js
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: '/src/lib/index.js',
output: {
filename: "main.js",
libraryTarget: "umd",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
options: { injectType: 'singletonStyleTag' }
},
"css-loader",
"sass-loader"
]
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'url-loader',
},
],
},
externals: [nodeExternals()]
};
The famous HelloWorld and the infamous InputBox
import React from "react";
import "./index.scss";
export const HelloWorld = () => {
return (
<div className="hello-wrapper">
Hello world!
</div>
);
};
export const InputBox = () => {
return(
<div>
<input />
</div>
)
}
/*
make components directory for better structuring and export everything here.
export {HelloWorld} from "./components/hello";
export {InputBox} from "./components/input";
*/
.hello-wrapper {
padding: 10px;
font-family: sans-serif;
font-size: 20px;
color: red;
}
<!--<!DOCTYPE html>-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React Json Viewer</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
import React from 'react';
import reactDom from 'react-dom';
import {HelloWorld, InputBox} from "./lib";
const App = () => {
return(
<div>
<HelloWorld />
<InputBox />
</div>
)
}
reactDom.render(<App/>, document.getElementById("root"));
export declare const HelloWorld;
export declare const InputBox;
Here's consumer react project app.js
import {HelloWorld, InputBox} from 'hello';
const App = () => {
return (
<div className="App">
<h1>This is consumer app</h1>
<HelloWorld />
<InputBox />
</div>
)
}
Everytime you update something, remember to update the version in package.json file, even if you update package or readme and follow the same steps.