so my webpack has been working fine. I needed a different structure then the default so I placed the webpack files in a build folder. As per documentation I placed the --config option in the package json but I am still not able to access the file in the debugger.
Below is my setup:
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"local": "webpack-dev-server --inline --progress --config build/webpack.local.conf.js",
"start": "npm run dev",
"build": "node build/build.js",
"build_dev": "node build/build.dev.js",
"build_stg": "node build/build.stg.js",
"build_prod": "node build/build.prod.js",
},
When I run the command node-nightly --inspect ./node_modules/webpack/bin/webpack.js
I get the error:
No configuration file found and no output filename configured via CLI option.
A configuration file could be named 'webpack.config.js' in the current directory.
In terms of my file structure I have under the root, a folder named build it contains the webpack config files (I was not sure how the structure is written on SO)
Version usage:
"webpack": "^3.12.0"
node 9.3
--config is a property on webpack. You are trying to set a --config property on webpack-dev-server webpack-dev-server
You can move your devserver to your webpack.config.js file
devServer: {
inline: true,
progress: true
}
and then refer to your webpack.config.js file directly in npm like so:
webpack --config ./build/yourfile.config.js
you can give any name you wish to the config file if you are using --config property else webpack will always try to find webpack.config.js in your projects root directory.
ELSE
you can create a webpack.config.js in your root and switch between config version on runtime like so:
//webpack.config.js
const TARGET = process.env.npm_lifecycle_event;
if (TARGET === 'build') {
module.exports = require('./buildScripts/webpack.config.dev');
}
else if (TARGET === 'build:prod') {
module.exports = require('./buildScripts/webpack.config.prod');
}
and in package.json you need the appropriate targets to match npm_lifecycle_event.
//package.json
"scripts": {
"build": "webpack --watch",
"build:prod": "webpack",
}
Related
I've been ask to take on a react project by a client and I'm struggling to understand how to prepare the files for hosting. I've used npm / webpack before, and I can see in the package.json the following:
"main": "index.js",
"scripts": {
"dev": "webpack --mode development --config server.config.js && webpack --mode development && nodemon server.js",
"watch": "webpack --mode development --watch",
"start": "webpack --mode production --config server.config.js && node server.js",
"heroku-postbuild": "webpack --mode production"
},
Also within the webpack.config.js file I have this:
output: {
path: path.join(__dirname, "dist"),
filename: "bundle.js"
},
I've run 'npm run heroku-postbuild'. This has led to a dist folder that gets created, which I expected would create the necessary compiled files to host on the server, however when I look in that directory all I get is a single 'bundle.js' file along with fonts and image assets.
What's confusing me is that there are zero generated HTML files.
Since I've not hosted a react site before, I'm not sure if this is what should be expected and if so, how do I set up hosting for this?
Thanks
By default, webpack does not create an index.html file for you. There are two main routes you can go:
Create your own index.html by hand, which loads your bundle.js with a <script> tag. Place this in a folder called public (or static -- the name isn't important), and then copy this into your dist folder at build time. This is easier in the short term.
Use the HtmlWebpackPlugin, which will generate an index.html file for you automatically, as part of the webpack build process. This is probably easier in the long run.
After adding authentication with passport and redux to my project, anytime I push my production ready code to my server it reuses an old build of the bundle file. If I use a one off server that had a much older build of the project it creates a new bundle, but any subsequent pushes do not.
At first I thought that it could be that webpack wasn't getting ran at all so I added a specific call in my start script and moved the dependencies away from devDependencies. This ultimately didn't change anything even after I could see from the server that web pack was being ran and building. Below are the scripts I have setup in package.json aswell as my webpack.config.
//Package.json
"scripts": {
"start": "npm-run-all --parallel build:prod lift",
"dev": "webpack --mode development && sails lift",
"start:debug": "npm-run-all --parallel open:client debug",
"open:client": "webpack-dev-server --mode development --open",
"build": "npm run build:prod",
"build:dev": "webpack --mode development",
"build:prod": "webpack --mode production"
}
//Webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
entry: "./assets/src/index.js"
},
output: {
path: __dirname + "/.tmp/public",
filename: "bundle.js",
publicPath: "/"
},
module: {
rules: [
{
use: "babel-loader",
test: /\.js$/,
exclude: /node_modules/
},
{
use: ["style-loader", "css-loader"],
test: /\.css$/
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "assets/src/index.html"
})
]
};
I know that I haven't employed best practices for production webpack but for now I just want to get it working on my server. My next step is to fine tune production webpack to give me the smallest bundle file possible but for right now I need to get webpack to rebundle the assets instead of using an old file. I'm sorta new to front and back end javascript development so a lot of this is new to me and I just initially setup webpack as quickly as possible.
Update - Solved
It seems that my issue was that my browser had cached the previous bundle.js file. Looking into a long term solution for this.
You need to remove the old build folder before re-bundling a new one. add a prepare npm hook to execute the script before packaging
"scripts": {
"prepare": "rm -rf /.tmp/public",
"start": "npm-run-all --parallel build:prod lift",
"dev": "webpack --mode development && sails lift",
"start:debug": "npm-run-all --parallel open:client debug",
"open:client": "webpack-dev-server --mode development --open",
"build": "npm run build:prod",
"build:dev": "webpack --mode development",
"build:prod": "webpack --mode production"
}
or
"scripts": {
"clean": "rm -rf /.tmp/public",
...
"build": "npm run clean && npm run build:prod",
"build:dev": "webpack --mode development",
"build:prod": "webpack --mode production"
}
I'm lost. I've been following a Udemy Webpack 4 tutorial on webpack and I am stuck on having different configs for different modes.
I can build from my production config just fine, but when it comes to running the node server, it's not set to production.
I have my main.js write this:
console.log(`Environment is: ${process.env.NODE_ENV`}
and I have only seen it in show as Development.
Here's my package.json's script to run production: I run npm run build and then npm run prod
"scripts": {
"build:dev": "webpack --config=config/webpack.dev.js",
"build": "webpack --config=config/webpack.prod.js",
"dev": "nodemon --inspect --watch config --watch src/server
src/server/main.js",
"prod": "cross-env NODE_ENV=production node src/server/main.js"
},
It was mentioned that I needed to define NODE_ENV in the webpack prod config in the plugin section. Here is how I have it:
new webpack.DefinePlugin({
'process.env': {
NODE_ENV:'"production"'
}
}),
I've tried it in different ways: 'process.env': {'NODE_ENV': JSON.Stringify("production")} and a couple of other ways and I have had no luck.
Here is my repository to see my complete config: https://github.com/PepperAddict/webpack-express
I would appreciate any help even recommendation on a better way to set this up. Thank you in advance!
Below is mine config using webpack 4
"prod": "webpack -p --mode=production --config webpack.prod.js",
"start": "webpack --mode=development --config webpack.dev.js",
And if you want to set NODE_ENV you can do like this
"prod": "SET NODE_ENV=production& webpack -p --mode=production",
Hope that help
Use Intellij IDEA's debug tool to webpack,
OS:MAC
npm script:
"scripts": {
"dev": " webpack-dev-server --inline --hot --display-error-details --content-base --config mvvm/build/webpack.dev.conf.js",
}
it tips:
To debug "build-distributor" script, make sure $NODE_DEBUG_OPTION string is specified as the first argument for node command you'd like to debug.
For example:
{ "start": "node $NODE_DEBUG_OPTION server.js" }
question:
Where to add this code($NODE_DEBUG_OPTION )?
Package.json configuration
First of all you have to create a new Debugging script like this:
"debug": "node $NODE_DEBUG_OPTION node_modules/.bin/webpack-dev-server --config ./path/to/webpack.config.js"
webpack configuration
You have to add this command line:
devtool: 'eval-source-map'
Editor configuration
and then you have to cofigurate your IDE:
and also this:
Thanks to an excellent answer by #McMath I now have webpack compiling both my client and my server. I'm now on to trying to make webpack --watch be useful. Ideally I'd like to have it spawn something like nodemon for my server process when that bundle changes, and some flavor of browsersync for when my client changes.
I realize it's a bundler/loader and not really a task runner, but is there some way to accomplish this? A lack of google results seems to indicate I'm trying something new, but this must have been done already..
I can always have webpack package to another directory and use gulp to watch it/copy it/browsersync-ify it, but that seems like a hack.. Is there a better way?
Install the following dependencies:
npm install npm-run-all webpack nodemon
Configure your package.json file to something as seen below:
package.json
{
...
"scripts": {
"start" : "npm-run-all --parallel watch:server watch:build",
"watch:build" : "webpack --watch",
"watch:server" : "nodemon \"./dist/index.js\" --watch \"./dist\""
},
...
}
After doing so, you can easily run your project by using npm start.
Don't forget config WatchIgnorePlugin for webpack to ignore ./dist folder.
Dependencies
npm-run-all - A CLI tool to run multiple npm-scripts in parallel or sequential.
webpack - webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
nodemon - Simple monitor script for use during development of a node.js app.
Faced the same problem and found the next solution - webpack-shell-plugin.
It
allows you to run any shell commands before or after webpack builds
So, thats my scripts in package.json:
"scripts": {
"clean": "rimraf build",
"prestart": "npm run clean",
"start": "webpack --config webpack.client.config.js",
"poststart": "webpack --watch --config webpack.server.config.js",
}
If I run 'start' script it launches next script sequence: clean -> start -> poststart.
And there is part of 'webpack.server.config.js':
var WebpackShellPlugin = require('webpack-shell-plugin');
...
if (process.env.NODE_ENV !== 'production') {
config.plugins.push(new WebpackShellPlugin({onBuildEnd: ['nodemon build/server.js --watch build']}));
}
...
"onBuildEnd" event fires only once after first build, rebuilds are not trigger "onBuildEnd", so nodemon works as intended
I like the simplicity of nodemon-webpack-plugin
webpack.config.js
const NodemonPlugin = require('nodemon-webpack-plugin')
module.exports = {
plugins: [new NodemonPlugin()]
}
then just run webpack with the watch flag
webpack --watch
In addition to #Ling's good answer:
If you want to build your project once, before you watch it with nodemon, you can use a webpack compiler hook. The plugin's code triggers nodemon in the done hook once after webpack has finished its compilation (see also this helpful post).
const { spawn } = require("child_process")
function OnFirstBuildDonePlugin() {
let isInitialBuild = true
return {
apply: compiler => {
compiler.hooks.done.tap("OnFirstBuildDonePlugin", compilation => {
if (isInitialBuild) {
isInitialBuild = false
spawn("nodemon dist/index.js --watch dist", {
stdio: "inherit",
shell: true
})
}
})
}
}
}
webpack.config.js:
module.exports = {
...
plugins: [
...
OnFirstBuildDonePlugin()
]
})
package.json:
"scripts": {
"dev" : "webpack --watch"
},
Hope, it helps.
There's no need to use plugins here. You could try running multiple nodemon instances like below. Try modifying the following script for your use case, and see if it works for you:
"scripts": {
"start": "nodemon --ignore './public/' ./bin/www & nodemon --ignore './public/' --exec 'yarn webpack'",
"webpack": "webpack --config frontend/webpack.config.js"
}
You don't need any plugins to use webpack and nodemon, just use this scripts on your package.json
"scripts": {
"start": "nodemon --ignore './client/dist' -e js,ejs,html,css --exec 'npm run watch'",
"watch": "npm run build && node ./server/index.js",
"build": "rimraf ./client/dist && webpack --bail --progress --profile"
},
#Ling has an answer very close to being correct. But it errors the first time somebody runs watch. You'll need to modify the solution as so to prevent errors.
Run npm install npm-run-all webpack nodemon
Create a file called watch-shim.js in your root. Add the following contents, which will create a dummy file and directory if they're missing.
var fs = require('fs');
if (!fs.existsSync('./dist')) {
fs.mkdir('./dist');
fs.writeFileSync('./dist/bundle.js', '');
}
Setup your scripts as so in package.json. This will only run watch if the watch-shim.js file runs successfully. Thereby preventing Nodemon from crashing due to missing files on the first run.
{
...
"scripts": {
"start": "npm run watch",
"watch": "node watch-shim.js && npm-run-all --parallel watch:server watch:build",
"watch:build": "webpack --progress --colors --watch",
"watch:server": "nodemon \"./dist/bundle.js\" --watch \"./dist/*\""
}
...
},
Assuming nodemon server.js touch the server.js file afterEmit:
// webpack.config.js
module.exports = {
// ...
plugins: [
// ...,
// 👇
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
require('child_process').execSync('touch server.js') // $ touch server.js
});
}
]
}
I tried most of the solution provided above. I believe the best one is to use nodemon-webpack-plugin .
It is very simple to use i.e. just add
const NodemonPlugin = require('nodemon-webpack-plugin')
to webpack file with
new NodemonPlugin() as your plugin.
Below are the scripts to use it:
"scripts": {
"watch:webpack-build-dev": "webpack --watch --mode development",
"clean-db": "rm -rf ./db && mkdir -p ./db",
"local-dev": "npm run clean-db && npm run watch:webpack-build-dev"
...
}
After this you can simply run npm run local-dev.
Adding a module to development is usually not as bad as adding to a production one. And mostly you will be using it for the development anyway.
This also doesn't require any additional package like nodemon or npm-run-all etc.
Also nodemon-webpack-plugin only works in watch mode.