Build index.html with webpack to use with dev server - javascript

Im using webpack for running my Three.js application with the following configuration in the webpack.config file:
module.exports = {
entry: `${__dirname}/src/tut15.js`,
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
},
plugins: [
new HtmlWebpackPlugin()
]
}
package.json
"scripts": {
"start": "webpack-dev-server --open",
"build": "webpack --config webpack.config.babel.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
With the HtmlWebpackPlugin it autogenerates the html for me. But since I want to create a custom html index file with some new tags this doesnt work for me. So I build the project
npm run-script build
and runs the index.html in the dist folder manually with my applied edits and everything works.
If I remove the HtmlWebpackPlugin from the webpack.config and build the project again and then run:
npm start
livereload works for my js files together with my new index.html with custom tags in the distfolder.
Questions:
It doesnt feels correct to create the changes in the dist folder. How can I generate a index.html straight from source? I guess that might solve all my problems being able to run dev server with a custom index.html
Or is it possible to get some livereload for the build as well?
after I have built my project it generates index.html and index.bundle in my distfolder. If I remove the index.bundle the project works anyway. What exactly does index.bundle do?
What is the best approach or do I need to build my project each time Im doing an update in my index file?
Thanks!

For questions regarding custom index.html and hot-reloading at least.
The plugin has some config you can add for templating.
new HtmlWebPackPlugin({
filename: 'index.html',
template: './public/index.html',
}),

Related

Webpack 4 ./src directory not found

I am trying to split the webpack config to base, dev and prod configs. Here is my entry section of webpack.base.babel.js file
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
Here is the entry section of webpackdev.babel.js file:
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'),
],
// Don't use hashes in dev mode for better performance
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js',
},
My start script in package.json looks like: "start": "webpack-dev-server --mode development"
But when I run npm start I get the bellow error:
ERROR in Entry module not found: Error: Can't resolve './src'
. I am on Windows 10. Could anybody explain what's wrong with my webpack config. I am specifying the entry file as app/app.js but still webpack is defaulting to src/index.js.
Thanks in advance.
Just hand in your webpack config explicitely by changing your npm start script to:
"start": "webpack-dev-server --config webpackdev.babel.js"
Webpack searches for webpack.config.js in the root folder automatically. Starting with v4, Webpack also claims to be a zero config bundler, so it will use opinionated defaults, if no config can be located. E.g.:
entry point of your project is assumed to be src/index
output will be put in dist/main.js
production mode will minify and do optimizations
Your config seems to be right, but Webpack can't find it and assumes the default entry, thus your error Can't resolve './src'.

Watch local dependencies with webpack-dev-server

I’m creating a Javascript library. Inside my project there’s a folder that contains examples of how to use the library. Inside each of the examples is a webpack config file with the entire purpose of bundling that example and serving it over webpack-dev-server with hot reloading. Each of these examples also has the library (at the root of the project) listed as a local NPM dependency. I have hot reloading working for each example and I have babel compiling the library at the root on a watch command.
Primary question: Is there a way that I can have the hot reloader of webpack-dev-server respond to changes in that local NPM dependency?
Secondary question: Is this intended to be the default behavior of webpack? If so, what is could be wrong with my machine/config file?
General/vague question: Am I doing this wrong? I feel like it should be a lot easier to serve local examples (I’m not interested in using Storybook either as the examples I’m writing aren’t in React, Vue, Angular, etc... it's all straight-up vanilla Javascript).
Here's my webpack.config.js file:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = (env, argv) => ({
mode: argv.mode,
entry: './index.js',
output: {
path: path.join(__dirname, '/dist'),
filename: 'index.bundle.js'
},
devtool: argv.mode === 'development' ? '#eval-source-map' : 'source-map',
devServer: {
port: 8080,
hot: true,
open: true,
stats: {
children: false, // Hide children information
maxModules: 0 // Set the maximum number of modules to be shown
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [new HtmlWebpackPlugin({ template: './index.html' })]
});
And my package.json file (note that syft.js is the local dependency I want to watch for changes):
{
"name": "with-grid",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "rm -rf dist && webpack --mode production",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "",
"devDependencies": {
"babel-loader": "^8.0.6",
"html-webpack-plugin": "^3.2.0",
"path": "^0.12.7",
"webpack": "^4.39.1",
"webpack-cli": "^3.3.7",
"webpack-dev-server": "^3.7.2"
},
"dependencies": {
"syft.js": "file:../.."
}
}
Folder structure is like such:
dist
index.js (Babel-generated file, what package.json points to, and the file that I want to be watched)
examples
with-grid
webpack.config.js (referenced above)
package.json (referenced above)
src
index.js (main src file)
Operating System: MacOS 10.14.6
Browser: Chrome 76
Node: 12.8.0
NPM: 6.10.3
Yarn: 1.17.3
I opted for a different strategy that now seems very obvious in retrospect. Rather than treating my library like a local node dependency that needs to be resolved, I can just simply import it locally.
When importing from my example folder, I do:
import syft from '../../src'; // Like a relative file
Instead of:
import syft from 'syft.js'; // Like an NPM package
After this small change, everything reloads as expected.
You can use npm link to create symbolic links between your React app and your local dependencies. Just make sure you build your local dependency to trigger reload in your React app.
Your local dependency should have a "main" and a "name" attributes in the package.json. webpack-dev-server will reload based on changes in your "main"
{
"name": "my-dep",
"main": "lib/index.js",
}
Run npm link next to the dependency package.json.
Run npm link my-dep in your React project - it will create a symbolic link between the two projects.
import myDep from 'my-dep in your React project. Reload will be triggered when you change lib/index.js
You can read more here https://medium.com/dailyjs/how-to-use-npm-link-7375b6219557
npm link: https://docs.npmjs.com/cli/link

How can I move "index.html" when using webpack?

Generally,when will "index.html" be loaded using webpack?
I want to move "index.html" to in build/.
I'm in trouble over data flow from npm start using webpack.
In package.json, "start" is defined as:
"node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js".
However,I couldn't find where it would jump from "webpack-dev-server.js".
I found two description about "index.html" in it as below:
.boolean("history-api-fallback").describe("history-api-fallback", "Fallback to /index.html for Single Page Applications.")
and
console.log("404s will fallback to %s", options.historyApiFallback.index || "/index.html");
when I try moving "index.html" to in build/, browser returned "Cannot Get error".
"index.html" and webpack.config.js are in same folder now.
./ index.html package.json src/ test/
../ build/ node_modules/ public/ style/
webpack.config.js
One way is to update the script (in package.json) so it copies index.html to the destination folder:
"scripts": {
"start": "node node_modules/.bin/webpack-dev-server --content-base src",
"build": "node node_modules/.bin/webpack && cp src/index.html build/index.html"
}
npm run build should now also copy src/index.html to build/index.html.
I'm not a webpack expert, but I faced the same issue, and was able to solve it using a plugin: html-webpack-plugin
First install it: npm install html-webpack-plugin --save-dev
Then edit your webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
//Your config here (entry, module, resolve, etc.)
devServer: {
contentBase: './build' //Or any other path you build into
},
plugins: [
//other plugins if any
new HtmlWebpackPlugin({
template: './index.template.html', //your template file
filename: 'index.html',
inject: 'body'
})
]
};
This is going to copy your index.template.html to ./build/index.html and serve files from there.
It will also inject all assets at the bottom of the <body> tag.
You can further costumize this setup to fit your need of course, just refer to the plugin docs.

Webpack: How to compile, write on disk and serve static content (js/css) using webpack-dev-server

I want to build my js/css code, write it on disk and serve it using webpack-dev-server in a single command. I don't want to set-up another server for production mode. How do we do it? Sharing my webpack.config.js file content below:
module.exports = {
watch: true,
entry: [
'./src/index.js'
],
output: {
path: __dirname +'/dist/',
publicPath: '/dist/',
filename: 'bundle.js'
},
module: {
loaders: [
{
exclude:/(node_modules)/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
},
devServer: {
historyApiFallback: true,
contentBase: './'
}
};
Please find the start script used in package.json below:
"start": "webpack-dev-server --progress --colors"
I am running "npm run start". Please help.
New webpack-dev-server is released, and it supports writeToDisk option.
devServer: {
writeToDisk: true
}
With webpack-dev-server v4.0.0+, devMiddleware is used:
devServer: {
devMiddleware: {
writeToDisk: true
}
}
webpack-dev-server uses a "virtual" Express server in conjunction with Sock.js to emulate a server running on your machine. Regarding compilation, webpack-dev-server does recompile the bundle whenever it detects code changes. This recompilation is served from memory, however, as opposed to the project's build directory (or, in your case, the dist directory). From the docs:
Using this configuration, webpack-dev-server will serve the static files in your build folder. It’ll watch your source files, and recompile the bundle whenever they are changed.
Regarding writing to your disk, webpack-dev-server does not do this. This is partially addressed by what's been written above. Additionally, note the following, also from the Webpack docs:
This modified bundle is served from memory at the relative path specified in publicPath (see API). It will not be written to your configured output directory. Where a bundle already exists at the same URL path, the bundle in memory takes precedence (by default).
To write to your disk, use the ordinary webpack module. Of course, as your question hints at, manual recompilation after every change is tedious. To address that chore, include the watch flag. From the Terminal, you could execute the command:
$ webpack --watch
I prefer to delegate this to an NPM script, however. Note that the -w flag below is equivalent to writing --watch.
// NPM `scripts` field:
"watch": "webpack -w"
If you want to run webpack-dev-server while also having your changes get recompiled and written to your output directory, you can add an additional NPM script like so:
"scripts": {
"serve": "npm run watch && npm run start",
"start": "webpack-dev-server --progress --colors",
"watch": "webpack -w"
}
Then, in your Terminal, just execute $ npm run serve to accomplish this.
If you're interested in the added convenience of automatic reload, you can do so by defining the following within the plugins field of your Webpack config file:
new webpack.HotModuleReplacementPlugin()
Note: This will likely require additional configuration settings for Babel. If I were you, I would take out the query field from your babel loader and, instead, delegate your Babel configuration to an external .babelrc file. A good one to use that is compatible with hot reloading might look like this:
{
"presets": ["env", "es2015", "react"],
"plugins": ["react-hot-loader/babel"]
}
On a side note, I've created a boilerplate repo for easily starting out projects with my desired structure. The Webpack configuration may of interest to, specifically. In particular, it employs Webpack 2 and includes other build tools like Babel (for transpilation), ESLint (syntax checker) as well as support for CSS/Sass and a variety of other file formats.
You can change your start script definition to this:
"start": "webpack --watch & webpack-dev-server --inline --progress --colors".
This sends the webpack watch-and-rebuild process to the background so that you can also hot-reload your modified modules as you change them with webpack-dev-server.
EDIT:
Either of these plugins may do what you want:
https://github.com/gajus/write-file-webpack-plugin
https://github.com/FormidableLabs/webpack-disk-plugin
webpack-dev-server serve files from memory, you can replace webpack-dev-server with webpack-simple-serve, it use webpack's watch feature, write the compiled files to disk and use serve-handler to serve.

How to get browser reload when editing html/jade files in webpack

This is part of the code I have in my webpack.config.js
const common = {
entry: {
style: PATHS.style,
app: PATHS.jsComp
},
output: {
path: PATHS.build,
filename: '[name].js'
},
module: {
loaders: [
{ test: /\.jade$/, loader: "jade" }
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack demo',
template: PATHS.template, // Load a custom template (ejs by default but can be changed)
inject: 'body' // Inject all scripts into the body (this is the default so you can skip it)
})
]
};
I'm showing you the section where I think the problem is, I don't think you needed the entire code, but it's basically a slightly modified version of this git file
When I run webpack-dev-server everything works. JavaScript and SASS changes do reload the browser but when I change by jade file, the browser doesn't reload. In the terminal I have tried running these variations of webpack-dev-server
webpack-dev-server
webpack-dev-server --inline --hot
webpack-dev-server --inline --hot --colors
webpack-dev-server --inline --hot --colors --content-base app
webpack-dev-server --inline --hot --colors --content-base app --host 0.0.0.0
webpack-dev-server --inline --hot --colors --host 0.0.0.0
None of the above 6 variations get the browser reloading when I made changes to the jade file.
Also, if I remember correctly, after every tutorial I have went through (before finding this setup), the browser never reloaded on html changes.
Is there anything else that I need to install (globaly or otherwise)
According to the documentation, you should do 3 things:
add an entry point to the webpack configuration: webpack/hot/dev-server.
add the new webpack.HotModuleReplacementPlugin() to the webpack configuration.
add hot: true to the webpack-dev-server configuration to enable HMR on the server.
As far as I see, I think the only thing of those 3 that you already did is using the hot: true. I use to run the webpack-dev-server via Gulp, so my configurations stay in a JS object, not in command line arguments.
Try this:
import webpack from 'webpack';
const common = {
entry: {
style: PATHS.style,
app: [
PATHS.jsComp,
'webpack/hot/dev-server', `webpack-dev-server/client?http://localhost:3000`
]
},
output: {
path: PATHS.build,
filename: '[name].js'
},
module: {
loaders: [
{ test: /\.jade$/, loader: "jade" }
]
},
devServer: {
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
title: 'Webpack demo',
template: PATHS.template, // Load a custom template (ejs by default but can be changed)
inject: 'body' // Inject all scripts into the body (this is the default so you can skip it)
})
]
};
Edit:
After discussing in the comments, I think that my answer does not address your case. I thought you were trying to reload the application after some Jade module (say, some AngularJS component were using import with jade-loader to load a Javascript template string from a Jade file) were changed. But as it turns out, you are trying to reload when your base HTML (well, Jade, but the base of your page) file is changed.
If you are using some modern Javascript framework (React, Angular etc), chances are your base HTML will be very small, and the real thing happens in Javascript.
Anyway, I don't think that your need is currently supported neither by webpack-dev-server or html-webpack-plugin.

Categories