I am having problems deploying my svelte web3 App to my VPS running Dokku.
The structure of the folder is as follows:
root
|-->svelte
|--> ...
I found some solutions to work with the two folders needing npm install around here. So I put:
"heroku-postbuild": "cd ./svelte && npm install && npm run build" and "cacheDirectories": ["./node_modules", "./svelte/node_modules"] in the root package.json.
But when the process comes to this point it fails with the following error:
remote: [!] Error: Cannot find module '#rollup/plugin-node-resolve'
remote: Require stack:
remote: - /tmp/build/svelte/rollup.config.js
remote: - /tmp/build/svelte/node_modules/rollup/dist/shared/loadConfigFile.js
remote: - /tmp/build/svelte/node_modules/rollup/dist/bin/rollup
I've tried changing the import to include the full paths etc. but nothing has worked so far. I have also changed the order of the imports, but the process fails with the first import in the rollup.config.
Any ideas?
package.json root:
"scripts": {
"heroku-postbuild": "cd ./svelte && npm install && npm run build"
},
"dependencies": {
"#openzeppelin/contracts": "^4.6.0",
"#truffle/hdwallet-provider": "^2.0.8",
"babel-polyfill": "^6.26.0",
"babel-register": "^6.26.0",
"dotenv": "^16.0.0",
"web3": "^1.7.3"
},
"cacheDirectories": ["./node_modules", "./svelte/node_modules"],
"engines": {
"node": "16.14",
"npm": "8.7.x"
}
}
package.json svelte (added all the dev dependencies again just in case)
{
"name": "app",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public --no-clear"
},
"devDependencies": {
"#rollup/plugin-commonjs": "^17.0.0",
"#rollup/plugin-node-resolve": "^11.0.0",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0"
},
"dependencies": {
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0",
"#rollup/plugin-commonjs": "^17.0.0",
"#rollup/plugin-node-resolve": "^11.0.0",
"rollup-plugin-css-only": "^3.1.0",
"rollup": "^2.3.4",
"rollup-plugin-svelte": "^7.0.0",
"#rollup/plugin-json": "^4.1.0",
"apexcharts": "^3.35.0",
"bootstrap": "^5.1.3",
"moment": "^2.29.2",
"rollup-plugin-copy": "^3.4.0",
"sirv-cli": "^2.0.0",
"svelte-web3": "^3.4.0"
}
}
rollup.config.js
import resolve from '#rollup/plugin-node-resolve';
import { nodeResolve } from '#rollup/plugin-node-resolve';
import svelte from 'node_modules/rollup-plugin-svelte';
import commonjs from 'node_modules/#rollup/plugin-commonjs';
import livereload from 'node_modules/rollup-plugin-livereload';
import { terser } from 'node_modules/rollup-plugin-terser';
import css from 'node_modules/rollup-plugin-css-only';
import json from 'node_modules/#rollup/plugin-json';
import copy from 'node_modules/rollup-plugin-copy'
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
json(),
nodeResolve(),
copy({
targets: [{
src: './node_modules/bootstrap/dist/**/*',
dest: 'public/vendor/bootstrap'
}]
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
```
I'm writing an Electron app with React and Typescript, using Webpack, Babel and ESLint but I'm having trouble setting:
mainWindow = new BrowserWindow({
title: "Biomech",
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
sandbox: true,
preload: path.join(__dirname, "./preload.js"),
nativeWindowOpen: true,
},
});
which I want as a security measure.
The reason being that, if I set the webPreferences as specified above, I need to use contextBridge and a preload script that binds the functions that are using IPC to the window. And the problem is that contextBridge is not being properly imported in my preload.ts:
import { contextBridge, ipcRenderer } from "electron";
import { readFileSync } from 'fs';
import { History } from 'history';
import { LIST_DRIVE_FILES_CHANNEL, LOAD_PREV_TEST_RESULTS_CHANNEL, OAUTH2_ACCESS_TOKEN_REQUEST_CHANNEL } from "../src/constants/ipcChannels";
import { VISUALIZE_RESULTS_PATH } from "../src/constants/urls";
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
exchangeCodeForAccessToken: (code: string) => {
ipcRenderer.invoke(OAUTH2_ACCESS_TOKEN_REQUEST_CHANNEL, code);
},
listDriveFiles: (accessToken: string) => {
ipcRenderer.invoke(LIST_DRIVE_FILES_CHANNEL, accessToken);
},
openDirectoryDialog: (history: History) => {
ipcRenderer.invoke(LOAD_PREV_TEST_RESULTS_CHANNEL).then((dialog: any) => {
if (dialog.canceled) { // canceled with one l is correct
return;
} else {
const selectedDirectory = dialog.filePaths[0];
console.log(readFileSync(selectedDirectory + "/README.md", 'utf-8'));
history.push(VISUALIZE_RESULTS_PATH);
}
})
}
}
);
The way I see it it's properly used like the examples I've seen here in SO, or in the Electron docs. But when I run my main process script: npm run dev:electron which is specified in my package.json:
{
"name": "electron-react-ts-app",
"version": "1.0.0",
"description": "Electron + React + Typescript",
"main": "./dist/main.js",
"preload": "./dist/preload.js",
"scripts": {
"dev": "concurrently --success first \"npm run dev:electron\" \"npm run dev:react\" -k",
"dev:electron": "NODE_ENV=development webpack --config webpack.electron.config.js --mode development && electron .",
"dev:react": "NODE_ENV=development webpack serve --config webpack.react.config.js --mode development",
"build:electron": "NODE_ENV=production webpack --config webpack.electron.config.js --mode production",
"build:react": "NODE_ENV=production webpack --config webpack.react.config.js --mode production",
"build": "npm run build:electron && npm run build:react",
"pack": "electron-builder --dir",
"dist": "electron-builder",
"lint": "eslint .",
"format": "prettier --write \"**/*.+(js|jsx|json|yml|yaml|css|md|vue)\""
},
"keywords": [],
"license": "MIT",
"build": {
"files": [
"dist/",
"node_modules/",
"package.json"
],
"productName": "Example",
"appId": "com.example.app",
"directories": {
"output": "dist"
}
},
"devDependencies": {
"#babel/preset-env": "^7.9.5",
"#babel/preset-react": "^7.9.4",
"#babel/preset-typescript": "^7.9.0",
"#types/electron-devtools-installer": "^2.2.0",
"#types/react-router-dom": "^5.1.7",
"#types/regenerator-runtime": "^0.13.0",
"dpdm": "^3.6.0",
"electron": "^11.2.1",
"electron-builder": "^22.7.0",
"electron-devtools-installer": "^3.1.1",
"eslint": "^7.18.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^4.5.1",
"husky": "^4.3.8",
"lint-staged": "^10.5.3",
"prettier": "^2.2.1",
"react-router-dom": "^5.2.0",
"webpack": "^5.11.1",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.1"
},
"dependencies": {
"#babel/core": "^7.12.10",
"#popperjs/core": "^2.6.0",
"#types/node": "^14.14.22",
"#types/react": "^17.0.0",
"#types/react-dom": "^17.0.0",
"axios": "^0.21.1",
"babel-loader": "^8.2.2",
"bootstrap": "^4.5.3",
"chokidar": "^3.5.1",
"core-js": "^3.8.3",
"css-loader": "^5.0.1",
"electron-fetch": "^1.7.3",
"fsevents": "^2.3.1",
"ini": "^2.0.0",
"jquery": "^3.5.1",
"react": "^17.0.1",
"react-bootstrap": "^1.4.0",
"react-dom": "^17.0.1",
"react-google-login": "^5.2.2",
"style-loader": "^2.0.0"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint && npm run format"
}
},
"lint-staged": {
"*.+(js|jsx)": "eslint --fix",
"*.+(json|css|md)": "prettier --write"
}
}
I get the following error: Cannot read property 'exposeInMainWorld' of undefined
webpack 5.19.0 compiled successfully in 1793 ms
App threw an error during load
TypeError: Cannot read property 'exposeInMainWorld' of undefined
at Object../electron/preload.ts (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:24:53)
at __webpack_require__ (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:128:41)
at /Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:252:11
at Object.<anonymous> (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:254:12)
at Module._compile (internal/modules/cjs/loader.js:1152:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1173:10)
at Module.load (internal/modules/cjs/loader.js:992:32)
at Module._load (internal/modules/cjs/loader.js:885:14)
at Function.f._load (electron/js2c/asar_bundle.js:5:12738)
at Module.require (internal/modules/cjs/loader.js:1032:19)
I've checked out this repo regarding Electron security and it doesn't look like he's doing things too different, at least at first glance, but I'm clearly messing something up.
Here's my webpack config (webpack.electron.config.js) in case it's useful:
const path = require("path");
module.exports = [
{
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
devtool: "source-map",
entry: {
main: {
import: "./electron/main.ts",
dependOn: "preload"
},
preload: "./electron/preload.ts"
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
},
target: "electron-main",
module: {
rules: [
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
node: {
__dirname: false,
},
},
];
I think the issue resides in you webpack.config file:
entry: {
main: {
import: "./electron/main.ts",
dependOn: "preload"
},
preload: "./electron/preload.ts"
},
Might be that webpack tries to resolve all "preload.ts" dependency at compile time, plus tries to bundle it together with main.ts file. And in such case it will never get access to contextBridge. The preload.js file should only be run in a separate "context" - "Isolated World" as they refer in the docs.
What I would try is:
remove the dependOn: and preload: lines from you webpack config.
convert preload.ts file to JS (ie. to CommonJS format) - try doing that with TS CLI for now
Your preload.js file should look more or less like this:
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
copy preload.js to a __dirname (in my case it was /dist)
run electron again
That was the only way I could access "contextBridge" object.
I'm trying to make a production version about my client side code to deploy later in AWS. When I compile and build my web application in development enviromet, everything works fine. But when I try to do it in production enviroment I've got a warning because I've got files bigger than 244KB.
To fix this problem, I have been following the indications of Dynamic Imports But, how you can see in this screen cap, I'm still getting a file very big:
My application use Node.js, React.js and webpack 4. This is my package.json
{
"name": "basketmetrics3",
"version": "1.0.0",
"description": "Basketball advanced stats",
"main": "server.js",
"scripts": {
"dev-webpack": "webpack-dev-server --hot --mode development",
"clean": "rm -rf ./dist",
"dev": "npm run build-dev && cross-env NODE_ENV=development nodemon --exec babel-node src/server/server.js --ignore ./src/client",
"build-dev": "npm run clean && npm run compile-dev",
"compile-dev": "NODE_ENV=development webpack -d --config ./webpack.config.babel.js --progress",
"compile": "NODE_ENV=production webpack -p --config ./webpack.config.babel.js --progress",
"build": "npm run clean && npm run compile",
"start": "npm run build && node ./dist/assets/js/main.bundle.js",
"heroku-postbuild": "webpack -p"
},
"dependencies": {
"#babel/polyfill": "^7.4.4",
"#material-ui/core": "^3.9.3",
"#material-ui/icons": "^3.0.2",
"bootstrap": "^4.3.1",
"cors": "^2.8.5",
"create-react-app": "^3.0.1",
"cross-env": "^5.2.0",
"d3": "^5.9.7",
"dotenv": "^7.0.0",
"express": "^4.17.1",
"express-graphql": "^0.7.1",
"graphql": "^14.4.2",
"jquery": "^3.4.1",
"morgan": "^1.9.1",
"mysql2": "^1.6.5",
"popper.js": "^1.15.0",
"react": "^16.8.6",
"react-bootstrap": "^1.0.0-beta.10",
"react-bootstrap-table-next": "^3.1.7",
"react-bootstrap-table2-paginator": "^2.0.7",
"react-dom": "^16.8.6",
"react-multi-language": "^0.4.2",
"react-router-dom": "^5.0.1",
"react-simple-tooltip": "^2.6.1",
"sequelize": "^4.44.2",
"validator": "^10.11.0"
},
"devDependencies": {
"#babel/cli": "^7.5.5",
"#babel/core": "^7.5.5",
"#babel/node": "^7.5.5",
"#babel/preset-env": "^7.5.5",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-register": "^6.26.0",
"css-loader": "^2.1.1",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.5.0",
"nodemon": "^1.19.1",
"path": "^0.12.7",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.38.0",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.7.2"
}
}
To run my application in development enviroment I do it with this command: npm run dev and to run my application in production environment I do it with npm run start.
And this is my webpack.config.babel.js:
import path from "path";
import HtmlWebpackPlugin from "html-webpack-plugin";
import MiniCssExtractPlugin from "mini-css-extract-plugin";
const devMode = process.env.NODE_ENV !== "production";
console.log("devMode: " + devMode);
module.exports = {
entry: "./src/client/index.js", //set entry file
// Resolve to output directory and set file
output: {
path: path.resolve("dist/assets"),
filename: "js/[name].bundle.js",
chunkFilename: "js/[name].bundle.js",
publicPath: "/assets" //It's mandatory to define this publicPath to get access to the website when we reload pages
//or we access to them directly with url's which have directories of second level like
//http://localhost:4000/directory-level-1/directory-level-2
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/client/index.html", //where is our template
filename: "../index.html", //where we are going to put our index.html inside the output directory
minify: {
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true
}
}),
new MiniCssExtractPlugin({
filename: "css/bundle.css",
minify: {
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true
}
})
],
//It help us to detect errors.
devtool: "source-map",
// Set dev-server configuration
devServer: {
inline: true,
contentBase: './dist',
port: 3000
},
// Add babel-loader to transpile js and jsx files
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use:[
{
loader: "babel-loader",
query: {
presets: [
"#babel/preset-react"
]
}
}
]
},
{
use: [
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
"css-loader"],
test: /\.css$/
},
{
test: /\.scss$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader",
options: {
sourceMap: true
}
},
{
loader: "saas-loader",
options: {
sourceMap: true
}
}
]
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: "url-loader",
options: {
limit: 10000,
publicPath: "/assets/images/",
outputPath: "./images/"
}
},
{
test: /\.(eot|ttf|woff|woff2)$/,
loader: "url-loader",
options: {
limit: 10000,
publicPath: "/assets/fonts/", //It's mandatory to get access to the fonts when we reload pages or access directly
outputPath: "./fonts/"
}
}
]
}
}
How can I split my code in files smaller than the file that I've got in this moment?
Edit I (solved):
One possible solution to split the client code in files with a size smaller than 244Kb could be adding this entry to webpack.config.babel.js file:
optimization: {
splitChunks : {
chunks: "all",
minSize: 30000,
maxSize: 100000,
}
},
Now, I've got several files with a size smaller than 100Kb. Any other option to do the same?
I've been using React 16.x.x and Jqwidgets 6.2.0 and React Boilerplate 3.7.0. My whole project was mounted over the React Boilerplate scaffold with its own configuration of webpack. I set jqwigets-scripts as a npm dependency and I tried excluding node_modules but including jqwidgets-scripts/jqwidgets-react through a regular expression as I read in some github. This is my current webpack.base.babel.js file:
...
module: {
rules: [
{
test: /\.js$/, // Transform all .js files required somewhere with Babel
exclude: /node_modules\/(?!(jqwidgets-scripts\/jqwidgets-react)\/).*/,
use: {
loader: 'babel-loader',
options: options.babelQuery,
},
},
...
With this configuration webpack compiles with no warnings and no errors like a charm, that is to say npm start. The big deal comes out to stage if I say npm run-script build, if so it complains with this:
Hash: 7b0feef0f8bbac0c9421
Version: webpack 4.27.1
Time: 41489ms
Built at: 2019-01-24 08:13:05
251 assets
Entrypoint main = runtime~main.43b100be02c6a9dbfc5a.js vendor.4d1e1f30cd3a7c98cfd8.chunk.js main.5ce13ffd96704eeb6b0d.chunk.js
ERROR in ./node_modules/jqwidgets-scripts/jqwidgets-react/react_jqxgrid.js 1216:12
Module parse failed: Unexpected token (1216:12)
You may need an appropriate loader to handle this file type.
| render() {
| return (
> <div id={this.state.id}>{this.props.value}{this.props.children}</div>
| )
| };
# ./app/modules/MyModule_1/index.js 43:0-70 954:37-44
# ./app/modules/MyModule_2/Loadable.js
# ./app/modules/MyModule_3/_nav.js
# ./app/modules/MyModule_4/index.js
# ./app/modules/MyModule_5/Loadable.js
# ./app/containers/MainLayout/_nav.js
# ./app/containers/MainLayout/index.js
# ./app/containers/MainLayout/Loadable.js
# ./app/containers/App/index.js
# ./app/app.js
# multi ./node_modules/react-app-polyfill/ie11.js ./app/app.js
I tried changing my webpack configuration as recommended in the official jqwidgets page (https://www.jqwidgets.com/community/topic/webpack-module-parse-failed/) like this:
module: {
rules: [
{
test: /\.js$/,
exclude: '/node_modules',
include: '/node_modules/jqwidgets-scripts/jqwidgets-react',
use: {
loader: 'babel-loader',
options: options.babelQuery
}
},
Then the complain is this while running npm start:
webpack built be60767d46a99fe48e6b in 1353ms
✖ 「wdm」:
ERROR in ./app/app.js 80:4
Module parse failed: Unexpected token (80:4)
You may need an appropriate loader to handle this file type.
| const render = messages => {
| ReactDOM.render(
> <AppContainer>
| <Provider store={store}>
| <LanguageProvider messages={messages}>
# multi ./node_modules/react-app-polyfill/ie11.js webpack-hot-middleware/client?reload=true ./app/app.js main[2]
Also, this is my babel.config.js
module.exports = {
presets: [
[
'#babel/preset-env',
{
modules: false,
},
],
'#babel/preset-react',
],
plugins: [
'styled-components',
'#babel/plugin-proposal-export-namespace-from',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-syntax-dynamic-import',
],
env: {
production: {
only: ['app'],
plugins: [
'lodash',
'transform-react-remove-prop-types',
'#babel/plugin-transform-react-inline-elements',
'#babel/plugin-transform-react-constant-elements',
],
},
test: {
plugins: [
'#babel/plugin-transform-modules-commonjs',
'dynamic-import-node',
],
},
},
};
My package.json:
{
"name": "react-boilerplate",
"version": "3.7.0",
"description": "A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices",
"repository": {
"type": "git",
"url": "git://github.com/react-boilerplate/react-boilerplate.git"
},
"engines": {
"npm": ">=5",
"node": ">=8.10.0"
},
"author": "Max Stoiber",
"license": "MIT",
"scripts": {
"analyze:clean": "rimraf stats.json",
"preanalyze": "npm run analyze:clean",
"analyze": "node ./internals/scripts/analyze.js",
"extract-intl": "node ./internals/scripts/extract-intl.js",
"npmcheckversion": "node ./internals/scripts/npmcheckversion.js",
"preinstall": "npm run npmcheckversion",
"prebuild": "npm run build:clean",
"build": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p --progress --hide-modules --display-optimization-bailout",
"build:clean": "rimraf ./build",
"start": "cross-env NODE_ENV=development env-cmd .env node server",
"start:tunnel": "cross-env NODE_ENV=development ENABLE_TUNNEL=true node server",
"start:production": "npm run test && npm run build && npm run start:prod",
"start:prod": "cross-env NODE_ENV=production node server",
"presetup": "npm i chalk shelljs",
"setup": "node ./internals/scripts/setup.js",
"clean": "shjs ./internals/scripts/clean.js",
"clean:all": "npm run analyze:clean && npm run test:clean && npm run build:clean",
"generate": "plop --plopfile internals/generators/index.js",
"lint": "npm run lint:js",
"lint:css": "stylelint './app/**/*.js'",
"lint:eslint": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts",
"lint:eslint:fix": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts --fix",
"lint:js": "npm run lint:eslint -- . ",
"lint:staged": "lint-staged",
"pretest": "npm run test:clean && npm run lint",
"test:clean": "rimraf ./coverage",
"test": "cross-env NODE_ENV=test jest --coverage",
"test:watch": "cross-env NODE_ENV=test jest --watchAll",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"prettify": "prettier --write"
},
"lint-staged": {
"*.js": [
"npm run lint:eslint:fix",
"git add --force"
],
"*.json": [
"prettier --write",
"git add --force"
]
},
"pre-commit": "lint:staged",
"resolutions": {
"babel-core": "7.0.0-bridge.0"
},
"dependencies": {
"#coreui/coreui": "^2.1.4",
"#coreui/coreui-plugin-chartjs-custom-tooltips": "^1.2.0",
"#coreui/icons": "^0.3.0",
"#coreui/react": "^2.1.1",
"ajv": "^6.6.1",
"babel-polyfill": "^6.26.0",
"block-ui": "^2.70.1",
"bootstrap": "^4.1.3",
"chalk": "^2.4.1",
"chart.js": "^2.7.3",
"classnames": "^2.2.6",
"compression": "^1.7.3",
"connected-react-router": "^4.5.0",
"core-js": "^2.6.0",
"env-cmd": "^8.0.2",
"exports-loader": "^0.7.0",
"flag-icon-css": "^3.2.1",
"font-awesome": "^4.7.0",
"fontfaceobserver": "2.0.13",
"history": "^4.7.2",
"hoist-non-react-statics": "3.0.1",
"immutable": "^3.8.2",
"intl": "^1.2.5",
"invariant": "^2.2.4",
"ip": "^1.1.5",
"is-url-external": "^1.0.3",
"isnumeric": "^0.3.3",
"jquery": "^3.3.1",
"jqwidgets-scripts": "^6.2.0",
"loadable-components": "^2.2.3",
"lodash": "^4.17.11",
"minimist": "1.2.0",
"moment": "^2.22.2",
"numeral": "^2.0.6",
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-chartjs-2": "^2.7.4",
"react-dom": "^16.6.3",
"react-helmet": "^5.2.0",
"react-hot-loader": "^4.6.3",
"react-intl": "^2.7.2",
"react-loadable": "^5.5.0",
"react-redux": "^5.1.1",
"react-router-dom": "^4.3.1",
"react-sizeme": "^2.5.2",
"reactstrap": "^6.5.0",
"redux": "^4.0.1",
"redux-immutable": "^4.0.0",
"redux-saga": "^0.16.2",
"reselect": "4.0.0",
"resize-sensor": "0.0.6",
"sanitize.css": "4.1.0",
"simple-line-icons": "^2.4.1",
"styled-components": "^4.1.2",
"warning": "^4.0.2"
},
"devDependencies": {
"#babel/cli": "7.1.2",
"#babel/core": "7.1.2",
"#babel/plugin-proposal-class-properties": "7.1.0",
"#babel/plugin-proposal-export-namespace-from": "^7.2.0",
"#babel/plugin-syntax-dynamic-import": "7.0.0",
"#babel/plugin-transform-modules-commonjs": "7.1.0",
"#babel/plugin-transform-react-constant-elements": "7.0.0",
"#babel/plugin-transform-react-inline-elements": "7.0.0",
"#babel/polyfill": "^7.0.0",
"#babel/preset-env": "7.1.0",
"#babel/preset-react": "7.0.0",
"#babel/register": "7.0.0",
"add-asset-html-webpack-plugin": "3.1.1",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-loader": "8.0.4",
"babel-plugin-dynamic-import-node": "2.2.0",
"babel-plugin-lodash": "3.3.4",
"babel-plugin-react-intl": "3.0.1",
"babel-plugin-react-transform": "3.0.0",
"babel-plugin-styled-components": "1.8.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.19",
"circular-dependency-plugin": "5.0.2",
"compare-versions": "3.4.0",
"compression-webpack-plugin": "2.0.0",
"copy-webpack-plugin": "^4.6.0",
"coveralls": "3.0.2",
"cross-env": "^5.2.0",
"css-loader": "1.0.0",
"enzyme": "3.7.0",
"enzyme-adapter-react-16": "1.6.0",
"enzyme-to-json": "3.3.4",
"eslint": "5.7.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-config-prettier": "3.1.0",
"eslint-import-resolver-webpack": "0.10.1",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-prettier": "3.0.0",
"eslint-plugin-react": "7.11.1",
"eslint-plugin-redux-saga": "0.9.0",
"express": "^4.16.4",
"file-loader": "2.0.0",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"http-proxy-middleware": "^0.19.1",
"image-webpack-loader": "^4.6.0",
"imports-loader": "0.8.0",
"jest-cli": "23.6.0",
"jest-styled-components": "6.2.2",
"lint-staged": "7.3.0",
"ngrok": "3.1.0",
"node-plop": "0.16.0",
"node-sass": "^4.11.0",
"null-loader": "0.1.1",
"offline-plugin": "5.0.5",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"plop": "2.1.0",
"pre-commit": "1.2.2",
"prettier": "1.14.3",
"react-app-polyfill": "0.1.3",
"react-test-renderer": "16.6.0",
"rimraf": "2.6.2",
"sass-loader": "^7.1.0",
"shelljs": "^0.8.3",
"style-loader": "0.23.1",
"stylelint": "9.6.0",
"stylelint-config-recommended": "2.1.0",
"stylelint-config-styled-components": "0.1.1",
"stylelint-processor-styled-components": "1.5.0",
"svg-url-loader": "2.3.2",
"terser-webpack-plugin": "1.1.0",
"uglifyjs-webpack-plugin": "^2.0.1",
"url-loader": "1.1.2",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "3.4.0",
"webpack-hot-middleware": "2.24.3 ",
"webpack-pwa-manifest": "3.7.1",
"whatwg-fetch": "3.0.0"
}
}
My webpack.prod.babel.js:
// Important modules this config uses
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const OfflinePlugin = require('offline-plugin');
const { HashedModuleIdsPlugin } = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = require('./webpack.base.babel')({
mode: 'production',
// In production, we skip all hot-reloading stuff
entry: [
require.resolve('react-app-polyfill/ie11'),
path.join(process.cwd(), 'app/app.js'),
],
// Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets
output: {
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].chunk.js',
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
warnings: false,
compress: {
comparisons: false,
},
parse: {},
mangle: true,
output: {
comments: false,
ascii_only: true,
},
},
parallel: true,
cache: true,
sourceMap: true,
}),
],
nodeEnv: 'production',
sideEffects: true,
concatenateModules: true,
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 10,
maxInitialRequests: 3,
name: true,
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
main: {
chunks: 'all',
minChunks: 2,
reuseExistingChunk: true,
enforce: true,
},
},
},
runtimeChunk: true,
},
plugins: [
// Minify and optimize the index.html
new HtmlWebpackPlugin({
template: 'app/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
inject: true,
}),
// Put it in the end to capture all the HtmlWebpackPlugin's
// assets manipulations and do leak its manipulations to HtmlWebpackPlugin
new OfflinePlugin({
relativePaths: false,
publicPath: '/',
appShell: '/',
// No need to cache .htaccess. See http://mxs.is/googmp,
// this is applied before any match in `caches` section
excludes: ['.htaccess'],
caches: {
main: [':rest:'],
// All chunks marked as `additional`, loaded after main section
// and do not prevent SW to install. Change to `optional` if
// do not want them to be preloaded at all (cached only when first loaded)
additional: ['*.chunk.js'],
},
// Removes warning for about `additional` section usage
safeToUseOptionalCaches: true,
}),
new CompressionPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
new WebpackPwaManifest({
name: 'React Boilerplate',
short_name: 'React BP',
description: 'My React Boilerplate-based project!',
background_color: '#fafafa',
theme_color: '#b1624d',
inject: true,
ios: true,
icons: [
{
src: path.resolve('app/images/icon-512x512.png'),
sizes: [72, 96, 128, 144, 192, 384, 512],
},
{
src: path.resolve('app/images/icon-512x512.png'),
sizes: [120, 152, 167, 180],
ios: true,
},
],
}),
new HashedModuleIdsPlugin({
hashFunction: 'sha256',
hashDigest: 'hex',
hashDigestLength: 20,
}),
],
performance: {
assetFilter: assetFilename =>
!/(\.map$)|(^(main\.|favicon\.))/.test(assetFilename),
},
});
My webpack.dev.babel.js:
/**
* DEVELOPMENT WEBPACK CONFIGURATION
*/
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
module.exports = require('./webpack.base.babel')({
mode: 'development',
// Add hot reloading in development
entry: [
require.resolve('react-app-polyfill/ie11'),
'webpack-hot-middleware/client?reload=true',
path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
],
// Don't use hashes in dev mode for better performance
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js',
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
// Add development plugins
plugins: [
new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
new HtmlWebpackPlugin({
inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
template: 'app/index.html',
}),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/, // exclude node_modules
failOnError: false, // show a warning when there is a circular dependency
}),
],
// Emit a source map for easier debugging
// See https://webpack.js.org/configuration/devtool/#devtool
devtool: 'eval-source-map',
performance: {
hints: false,
},
});
And finally my webpack.base.babel.js:
/**
* COMMON WEBPACK CONFIGURATION
*/
const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const config = require('../../server/config');
// Remove this line once the following warning goes away (it was meant for webpack loader authors not users):
// 'DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic,
// see https://github.com/webpack/loader-utils/issues/56 parseQuery() will be replaced with getOptions()
// in the next major version of loader-utils.'
process.noDeprecation = true;
module.exports = options => ({
mode: options.mode,
entry: options.entry,
output: Object.assign(
{
// Compile into js/build.js
path: path.resolve(process.cwd(), 'build'),
publicPath: '/',
},
options.output,
), // Merge with env dependent settings
optimization: options.optimization,
module: {
rules: [
{
test: /\.js$|\.jsx$/, // Transform all .js files required somewhere with Babel
exclude: /node_modules\/(?!(jqwidgets-scripts\/jqwidgets-react)\/).*/,
use: {
loader: 'babel-loader',
options: options.babelQuery,
},
},
// {
// test: /\.js$|\.jsx$/,
// exclude: '/node_modules',
// include: '/jqwidgets-scripts/jqwidgets-react',
// use: {
// loader: 'babel-loader',
// options: options.babelQuery
// }
// },
{
// Preprocess our own .css files
// This is the place to add your own loaders (e.g. sass/less etc.)
// for a list of loaders, see https://webpack.js.org/loaders/#styling
test: /\.scss$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
// Preprocess 3rd party .css files located in node_modules
test: /\.css$/,
include: /node_modules/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(eot|otf|ttf|woff|woff2)$/,
use: 'file-loader',
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
// Inline files smaller than 10 kB
limit: 10 * 1024,
noquotes: true,
},
},
],
},
{
test: /\.(jpg|png|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// Inline files smaller than 10 kB
limit: 10 * 1024,
},
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
enabled: false,
// NOTE: mozjpeg is disabled as it causes errors in some Linux environments
// Try enabling it in your environment by switching the config to:
// enabled: true,
// progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '65-90',
speed: 4,
},
},
},
],
},
{
test: /\.html$/,
use: 'html-loader',
},
{
test: /\.(mp4|webm)$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
},
},
},
],
},
plugins: options.plugins.concat([
// Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
// inside your code for any environment checks; Terser will automatically
// drop any unreachable code.
/* new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}), */
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(config.env),
HOST: JSON.stringify(config.server_host),
PORT: JSON.stringify(config.server_port)
},
}),
new webpack.NamedModulesPlugin(),
new CopyWebpackPlugin([{ from: 'static' }]),
]),
resolve: {
modules: ['node_modules', 'app'],
extensions: ['.js', '.jsx', '.react.js'],
mainFields: ['browser', 'jsnext:main', 'main'],
alias: {
moment$: 'moment/moment.js',
},
},
devtool: options.devtool,
target: 'web', // Make web variables accessible to webpack, e.g. window
performance: options.performance || {},
});
My question is, how to configure webpack in order to work properly in production mode?