Having trouble accessing subroutes of vue app directly - vue.js

I'm working on a express + vue project with the following structure (see below), and I have trouble accessing subroutes of the vue app directly in production (hosted on Heroku). For instance, I can go to www.example.com and can access subroutes from the index page, but typing www.example.com/subpage directly gives the following errors.
More context: I currently manually copy the built files from frontend/dist to public. To get it to work, I am using publicPath ./ in vue.config.js. In development if I change the publicPath to /, I don't get the above problem.
Uncaught SyntaxError: Unexpected token '<' (at chunk-vendors.25f4b4fa.js:1:1)
app.c661c8f0.js:1
Uncaught SyntaxError: Unexpected token '<' (at app.c661c8f0.js:1:1)
manifest.json:1
Manifest: Line: 1, column: 1, Syntax error.
Folder Structure
mainfolder
--> frontend (vue development files)
---> dist
--> src (express backend)
--> public (where I copy the built vue files)
---> js
---> css
---> img
---> index.html
express app.js file
app.use(express.static('public'));
app.use('*', function(req, res, next) {
res.sendFile(path.resolve(__dirname, '../public/index.html'));
});
app.use(require('connect-history-api-fallback')());

You are not serving static files properly. Let Node.Js ecosystems take care of returning your UI file.
// app.use(express.static('public'));
// app.use('*', function(req, res, next) {
// res.sendFile(path.resolve(__dirname, '../public/index.html'));
// });
app.use('/', express.static(path.join(__dirname, '../public')));
app.use(require('connect-history-api-fallback')());
If the index.htm does not load its JavaScript dependencies, you need to rebuild the UI taking care of subdomains.
To serve your static files in a better way, please look at this link.

Related

How to properly set up Vite, Express, Tailwind web app

Scenario:
I am making a basic web app using Vite & Tailwind. I set up my app as normal installing Vite, and Tailwind, and got everything running fine by testing for Tailwind css on localhost:5500.
Problem:
Once I added an Express server to the mix, and it sends the index.html in response to a 'GET' request # '/', I no longer get the compiled CSS from tailwind.
Is this an uncommon setup that should be troublesome?
You could possibly use a middleware like express.static
Example:
const express = require('express')
const app = express()
app.use(express.static(__dirname + '/public'))
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
In this example, the express.static middleware is used to serve the public directory, which is where the compiled CSS files from Tailwind will be located. Then the express server will send the index.html file in response to a GET request at the root '/' path.
Extra: Alternatively you can also use Webpack or Parcel , which can automatically handle the process of bundling and serving your CSS files

Error: Failed to lookup view "home" in views directory

I developed a small application with electron and expressjs. In development mode, the app works fine. But after packaging the app for the production mode I got the error that the home view is not found. Here are some details:
The main route in app.js
router.get('/', async (req,res) => {
res.render('home');
});
My file structure is:
In order to solve the problem I tried the following:
router.get('/', async (req,res) => {
var path = require('path');
res.render(path.join(__dirname+'/views/home.ejs'));
});
Now the view is loaded, but all the css and js files within home.ejs are not loaded
All css and js files are located under the public folder and within home.ejs, i refer to these files as follows:
<script src="/js/vendor/jquery-3.6.0.min.js"></script>
<script src="/js/vendor/bootstrap.bundle.min.js"></script>
<script src="/js/home.js"></script>
I tried both electron packagers, electron-forge and electron-builder and had the same error. Can you please help??
You need an express.static(...) statement somewhere in your app to serve the css and js files. How does that look? The following should work:
app.use("/js", express.static(__dirname + "/public/js"));
app.use("/css", express.static(__dirname + "/public/css"));

Express is serving files without going through route handlers?

I have the following code:
const app = express();
app.use(express.static(path.resolve('../frontend/dist')));
const server = http.createServer(app);
app.get('/', (req, res) => {
console.log('received request');
res.sendFile(path.resolve('../frontend/dist/index.html'));
});
If I comment out the app.get handler, index.html is served at localhost:3000 anyway, apparently due to the second line. The get handler is not actually executing - received request is never printed in the console.
But without the second line, it can't serve static assets and JS & CSS fail to load. What am I doing wrong here? Why is the static asset config causing the route to be ignored?
express.static() is a generic route handler. It tries to match incoming requests to specific files at a target location in your file system. One of the special features it has is that if it gets a request for / it will look for index.html in the target directory.
You can see the feature described in the doc and, in fact, there's an option { index: false} that can turn the feature off if you don't want it to serve index.html automatically.

Built Vue SPA not working when using "publicPath"

I set a public path in vue.config.js like
module.exports = {
publicPath: '/subpath'
};
it works fine when I start the devlopment server with npm run serve (vue-cli-service serve). The app becomes available at localhost:8080/subpath which is exactly what I want. It uses vue-router and at least in development it seems to work perfekt with the /subpath as publicPath.
Problem
I am using Express to serve the app files. Running npm run build the app will be built and stored to ./dist folder (default output folder).
// simplified server.js
app.use(express.static(path.join(__dirname, '/dist')));
app.get('/', (req, res, next) => {
res.sendfile('./dist/index.html');
});
After starting my express server and visiting my browser at localhost:<port>/subpath or localhost:<port> it can't find the necessary files.
// EXAMPLE FROM BROWSER CONSOLE
GET http://localhost:5050/subpath/js/app.6c6daa90.js net::ERR_ABORTED 404 (Not Found)
Which somehow looks obvious to me but I don't know how to set the express server correctly to respect the publicPath setting . Maybe there is a different approach ?
Attempt #1
I made a little change in my express server.js
// app.use(express.static(path.join(__dirname, '/dist')));
/* NEW */
app.use('/subpath', express.static(path.join(__dirname, '/dist')));
This way it should serve the static files from the /dist folder when requested with /subpath/app.js
Result
From Browser console when requesting localhost:<port>/subpath or localhost:<port>
Refused to load the font 'data:application/font-woff2;base64,<omitted>' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.
Refused to load the image 'http://localhost:5050/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.
I played around with express.static and this combination seems to work for me
const path = require('path');
const express = require('express');
const history = require('connect-history-api-fallback');
const app = express();
app.use(history());
app.use(express.static(path.join(__dirname, '/dist')));
app.use('/subpath', express.static(path.join(__dirname, '/dist')));
const listener = app.listen(5050, () => {
console.log(`Open http://localhost:${port} in your browser`);
});
Sidenote : Adding connect-history-api-fallback was not required to solve the initial problem but is required for vue-router to work properly when in history mode.

Serving static files from an express/node.js application

Hi I am a newbie and started to learn about node recently. I took an Heroku tutorial on websockets (https://devcenter.heroku.com/articles/node-websockets) and adapted it for a specific project I was working on. In the example code there was a single index.html file with some embedded javascript. I moved this script out to a separate file and referenced it in the HTML. Everything worked fine locally but doesn't work when i deploy to Heroko. I chatted with the very helpful team at Heroku who informed me that my server side code is serving up all files as HTML and I need to change the code. They gave me some pointers and I tried as many things as I could over several days but to no avail. In the end they recommended coming to this forum as a way to solve the problem as it is beyond their scope. The existing code that serves up the index.html file is as follows:
const express = require('express');
const SocketServer = require('ws').Server;
const path = require('path');
const PORT = process.env.PORT || 3000;
const INDEX = path.join(__dirname, 'index.html');
const server = express()
.use((req, res) => res.sendFile(INDEX) )
.listen(PORT, () => console.log(Listening on ${ PORT }));
At first i edited this to include the line:
app.use(express.static('public'))
but this didn't work. I then amended as follows and it still doesn't work:
const INDEX = path.join(__dirname, 'index.html');
const JS = path.join(__dirname, 'client.js');
const server = express()
.use((req, res) => {
res.sendFile(INDEX);
res.sendFile(JS);
I have looked at other tutorials that work when i run them in isolation but when I try to adapt my above code it simply doesn't work. I would really appreciate if someone out there could point me in the right direction.
BTW this is what Heroku told me:
"To explain a bit further this error Uncaught SyntaxError: Unexpected token < is because the URL for http://thawing-journey-33085.herokuapp.com/client.js isn't serving a javascript file but is instead trying to serve the HTML for the homepage. This suggests you have an issue with the routing in your application which you'll need to review. This is probably because your server.js file doesn't check for any particular URL before sending the index.html file."
Thanks
I serve my static files like this:
// define the folder that will be used for static assets
app.use(Express.static(path.join(__dirname, '../public')));
// handle every other route with index.html, which will contain
// a script tag to your application's JavaScript file(s).
app.get('*', function (request, response){
response.sendFile(path.resolve(__dirname, '../public', 'index.html'));
});
This way i set the static folder in the express.static middleware so i can serve the files. And then i redirect all url request to the index.html
To know more: express static