I've create a react app through the create-react-app package and I want to get a Add To Homescreen button on my app. I run my development server from yarn start on localhost:8080. I've added the Bypass user engagement checks in Chrome through > chrome://flags/#bypass-app-banner-engagement-checks
I navigate to my app in my browser (on the pc) and go into responsive manipulation, but I see a error in the log:
Site cannot be installed: Page has no manifest URL
The create-react-app plugin puts the Manifest in the ./public folder but I'm using webpack-dev-server to start the app "start": "webpack-dev-server --mode development --open --hot --env.presets serviceworker",
In my webpack.config.js I have:
module.exports = {
entry: './src/index.tsx',
devServer: {
contentBase: '/public'
},
My ./public folder contains the manifest.json file. But when I start the app I get the error:
Site cannot be installed: Page has no manifest URL
I think my webpack is not pointing to the correct folder, or the webpack config is wrong some other way.
The path in the contentBase should start with a .. So:
devServer: {
contentBase: './public'
},
And in my src/index.html:
<link href="manifest.json" rel="manifest" />
Now the manifest is loaded.
Related
everyone
I created a React app in order to build an electron app. I'm trying to use electron-builder to create the installers. I'm working on Ubuntu trying to generate a .deb.
I didn't use create-react-app, I used a boilerplate I already had, but I don't know if this is the problem.
I can make it work as long as I edit the index.html the webpack generates in the build folder. I have to change the path to main.css and build.js from /main.css and /build.js to ./main.css and ./build.js.
I read that I have to use the "homepage" property in package.json, but it's not working, seems to be ignored.
My folder structure is like:
package.json
src/
config/
main_electron_file.js
build/ #generated by webpack when I run the 'build:prd' command
public/ #empty
package.json
{
"name": "frontend",
"version": "1.0.0",
"description": "",
"main": "./main_electron_file.js",
"scripts": {
"dev": "./node_modules/.bin/webpack-dev-server --config ./config/webpack.config.dev.js --mode development --open --hot",
"build:prd": "./node_modules/webpack/bin/webpack.js --mode production --config ./config/webpack.config.prd.js --env.NODE_ENV=production --progress",
"electron": "electron .",
"start": "npm run dev && npm run electron",
"start:dev": "ELECTRON_START_URL=http://localhost:3000 electron .",
"dist": "build"
},
"keywords": [],
"author": {
"name": "name",
"email": "email#mail.com"
},
"license": "ISC",
"dependencies": {
...
},
"devDependencies": {
...
},
"homepage": "./",
"build": {
"appId": "com.myself.myapp",
"linux": {
"target": [
"deb"
]
}
}
}
main_electron_file.js
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron');
const path = require('path');
const url = require('url');
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow() {
const startUrl = process.env.ELECTRON_START_URL || url.format({
pathname: path.join(__dirname, 'build/index.html'),
protocol: 'file:',
slashes: true
});
// Create the browser window.
mainWindow = new BrowserWindow({ width: 800, height: 600, resizeble: false });
mainWindow.setResizable(false);
// and load the index.html of the app.
// win.loadURL('http://localhost:3000');
mainWindow.loadURL(startUrl);
// Open the DevTools.
mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
By the way. I'm not building it. I'm running it pointing to the index.html in the dist, as I would do in production mode. So i'm running npm run build:prd and then npm run electron
ANy ideas how I could make this process automatic?
Please try adding this line in your index.html
<base href="./">
And your main.css and build.js directory should be set relative to your index.html in build folder
What worked for me was:
Add to webpack config:
output: {
publicPath: './',
...
}
This tells webpack to have every link between files it creates based at the same directory.
As suggested by carlokid, add to index.html:
< base href="./" />
In my app js
app.use(express.static(join(__dirname, '/dist')))
Webpack config:
module.exports = {
entry: "./src/main.js",
output: {
path: join(__dirname, "/dist/js/"),
filename: "bundle.js",
publicPath: "/"
},
mode: "development"
// ...
};
In my footer.hbs
<script src="/js/bundle.js"></script>
In my package.json Scripts
"startw": "webpack-dev-server --open",
"server": "node app.js",
When I make a change in any js file, webpack is compiling but it does not overwrite /js/bundle.js. How can I make webpack recompile my changed bundle js to overwrite dist/js/bundle.js ?
I have tried
https://webpack.js.org/guides/development/#using-webpack-dev-server
and
webpack-dev-middleware
For production, I use
"dev": "./node_modules/.bin/webpack -p --watch",
This compiled as expected to dist/js/bundle.js but this is tedious to run it each time I make a simple change to a js file.
I want to inject the auto compiled output js to use it in my app. I dont mind refreshing the page myself and do not care if I dont get to use HMR.
My project directory Structure is :
mcdist <build output folder>
- assets
index.html
- css
main.css
- js
app.js
lib.js
- ng-app
<all HTML Files>
- images
src
- images
1.png
2.png
- javascripts
- ng-app
- components
1.js
- directives
2.js
- filters
3.js
- stylesheets
1.scss
2.scss
index.html
app.js
node_modules
webpack.config.js
package.json
My webpack.config looks like this :
var path = require('path');
var webpack = require('webpack');
var config = {
entry: {
app: ['./app.js'],
lib: ['./lib.js']
},
output: {
path: path.join(__dirname, '/mcdist/assets/js/'),
filename: 'app.js',
publicPath: "/public/js/"
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'lib',
filename: 'lib.js',
minChunks: Infinity
}),
new webpack.NamedModulesPlugin()
],
devServer: {
proxy: [{
context: [
'/mcdist/api',
'/mcdist/appConfig',
'/mcdist/j_spring_security_logout'
],
target: 'http://localhost:8080',
secure: false
}],
port: 9000
}
};
module.exports = config
I run:
webpack-dev-server --inline
I create build folder 'mcdist' using npm command as :
"build:js": "uglifyjs mcdist/assets/js/app.js -m -o mcdist/assets/js/app.js",
My src/app.js looks like this :
require('./src/javascripts/ng-app/config/init-config.js');
require('./src/javascripts/ng-app/config/theme-config.js');
require('./src/javascripts/ng-app/components/dialog-message/dialog-message.service.js');
require('./src/javascripts/ng-app/components/footer/footer.controller.js');
require('./src/javascripts/ng-app/components/topbar/topbar.controller.js');
and many more files as list in require format in app.js
Now every time I make changes in HTML, JS files I need to create new build so changes get pushed to 'mcdist' folder (JS files gets concatenated and uglified in single app.js and all HTML files pushed to ng-app folder inside 'mcdist' folder.)
AND I've to RESTART WEBPACK dev server to see changes reflected.
This is very painful in local/development environment as changing small code needs build and restart, which is not the case with Grails application.
is there any way I can avoid restarting a server and just make changes to them hot-reloaded ? I've already tried running with --hot and --inline approaches but nothing had luck.
Help is most appreciated.
I'm new to WebPack and React, and am having an issue getting my settings correct.
My directory structure is:
/project/
/src/
index.html
app.js
/static/
/images
My "output" WebPack config section is:
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
},
My React app runs fine, but I'm not getting any images served with urls as such:
<img src="/static/images/logo.jpg" />
If I change the image src values to:
<img src="/src/static/images/logo.jpg" />
they work, but of course, that's not going to be the case in production, since the /src/ directory wouldn't be deployed. It seems I have the root set incorrectly.
Do I need to tell WebPack to copy the "static" directory into "dist"? or? Advice appreciated.
After some digging, what I actually wanted was: https://webpack.github.io/docs/webpack-dev-server.html#content-base
Then I modified my npm start script to:
"./node_modules/.bin/webpack-dev-server --hot --inline --progress --content-base src/"
and now relative image paths are happy again.
You can import (or require) images with webpack.
Add the file-loader to the webpack config (make sure file-loader is installed):
{
test: /\.(png|gif|jpg)$/,
include: [
path.join(__dirname, 'static')
],
loader: 'file',
}
You can then import an image:
import Image1 from '../static/images/image1.png';
and use it like this:
<img src={Image1} width="64" height="64" />
Webpack will place all imported images in the "dist" directory.
React router allows react apps to handle /arbitrary/route. In order this to work, I need my server to send the React app on any matched route.
But webpack dev server doesn't handle arbitrary end points.
There is a solution here using additional express server.
How to allow for webpack-dev-server to allow entry points from react-router
But I don't want to fire up another express server to allow route matching. I just want to tell webpack dev server to match any url and send me my react app. please.
I found the easiest solution to include a small config:
devServer: {
port: 3000,
historyApiFallback: {
index: 'index.html'
}
}
I found this by visiting: PUSHSTATE WITH WEBPACK-DEV-SERVER.
historyApiFallback option on official documentation for webpack-dev-server explains clearly how you can achieve either by using
historyApiFallback: true
which simply falls back to index.html when the route is not found
or
// output.publicPath: '/foo-app/'
historyApiFallback: {
index: '/foo-app/'
}
Adding public path to config helps webpack to understand real root (/) even when you are on subroutes, eg. /article/uuid
So modify your webpack config and add following:
output: {
publicPath: "/"
}
devServer: {
historyApiFallback: true
}
Without publicPath resources might not be loaded properly, only index.html.
Tested on Webpack 4.6
Larger part of config (just to have better picture):
entry: "./main.js",
output: {
publicPath: "/",
path: path.join(__dirname, "public"),
filename: "bundle-[hash].js"
},
devServer: {
host: "domain.local",
https: true,
port: 123,
hot: true,
contentBase: "./public",
inline: true,
disableHostCheck: true,
historyApiFallback: true
}
Works for me like this
devServer: {
contentBase: "./src",
hot: true,
port: 3000,
historyApiFallback: true
},
Working on riot app
My situation was a little different, since I am using the angular CLI with webpack and the 'eject' option after running the ng eject command. I modified the ejected npm script for 'npm start' in the package.json to pass in the --history-api-fallback flag
"start": "webpack-dev-server --port=4200 --history-api-fallback"
"scripts": {
"ng": "ng",
"start": "webpack-dev-server --port=4200 --history-api-fallback",
"build": "webpack",
"test": "karma start ./karma.conf.js",
"lint": "ng lint",
"e2e": "protractor ./protractor.conf.js",
"prepree2e": "npm start",
"pree2e": "webdriver-manager update --standalone false --gecko false --quiet",
"startold": "webpack-dev-server --inline --progress --port 8080",
"testold": "karma start",
"buildold": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"},
I agree with the majority of existing answers.
One key thing I wanted to mention is if you hit issues when manually reloading pages on deeper paths where it keeps the all but the last section of the path and tacks on the name of your js bundle file you probably need an extra setting (specifically the publicPath setting).
For example, if I have a path /foo/bar and my bundler file is called bundle.js. When I try to manually refresh the page I get a 404 saying /foo/bundle.js cannot be found. Interestingly if you try reloading from the path /foo you see no issues (this is because the fallback handles it).
Try using the below in conjunction with your existing webpack config to fix the issue. output.publicPath is the key piece!
output: {
filename: 'bundle.js',
publicPath: '/',
path: path.resolve(__dirname, 'public')
},
...
devServer: {
historyApiFallback: true
}
If you choose to use webpack-dev-server, you should not use it to serve your entire React app. You should use it to serve your bundle.js file as well as the static dependencies. In this case, you would have to start 2 servers, one for the Node.js entry points, that are actually going to process routes and serve the HTML, and another one for the bundle and static resources.
If you really want a single server, you have to stop using the webpack-dev-server and start using the webpack-dev-middleware within your app-server. It will process bundles "on the fly" (I think it supports caching and hot module replacements) and make sure your calls to bundle.js are always up to date.
For me I had dots "." in my path e.g. /orgs.csv so I had to put this in my webpack confg.
devServer: {
historyApiFallback: {
disableDotRule: true,
},
},
You can enable historyApiFallback to serve the index.html instead of an 404 error when no other resource has been found at this location.
let devServer = new WebpackDevServer(compiler, {
historyApiFallback: true,
});
If you want to serve different files for different URIs, you can add basic rewriting rules to this option. The index.html will still be served for other paths.
let devServer = new WebpackDevServer(compiler, {
historyApiFallback: {
rewrites: [
{ from: /^\/page1/, to: '/page1.html' },
{ from: /^\/page2/, to: '/page2.html' },
{ from: /^\/page3/, to: '/page3.html' },
]
},
});
I know this question is for webpack-dev-server, but for anyone who uses webpack-serve 2.0. with webpack 4.16.5; webpack-serve allows add-ons.You'll need to create serve.config.js:
const serve = require('webpack-serve');
const argv = {};
const config = require('./webpack.config.js');
const history = require('connect-history-api-fallback');
const convert = require('koa-connect');
serve(argv, { config }).then((result) => {
server.on('listening', ({ server, options }) => {
options.add: (app, middleware, options) => {
// HistoryApiFallback
const historyOptions = {
// ... configure options
};
app.use(convert(history(historyOptions)));
}
});
});
Reference
You will need to change the dev script from webpack-serve to node serve.config.js.