Wildcards in ServiceWorker / Cache API - javascript

I am using ServiceWorker and in dev mode works perfectly, my problem is that in production mode my bundle name is generated using hash, e.g. 1234das3123ad5.bundle.js, so the service worker is not caching it. My sw code looks like:
self.addEventListener('install', function(event) {
// pre cache a load of stuff:
event.waitUntil(
caches.open('mycache').then(function(cache) {
return cache.addAll([
'/dist/bundle.js',
'/dist/app.css',
'/dist/index.html',
'https://cdnjs.cloudflare.com/ajax/libs/antd/2.7.2/antd.css'
]);
})
)
});
In the docs of Cache API I dont see any example on how I can achieve that.
Obviously I could cache everything under the dist folder, having something like:
self.addEventListener('install', function(event) {
// pre cache a load of stuff:
event.waitUntil(
caches.open('mycache').then(function(cache) {
return cache.addAll([
'/dist/',
]);
})
)
});
But I dont find it an elegant, good in long term, solution. Is it a way to have wild cards in the Cache? Something like '/dist/*.bundle.js' ?

The web doesn't have the concept of folders, specifically there isn't a way for a browser to know all the valid URLs starting with a prefix.
The rest of your site must be handling the URL changes for revisioning assets somehow, so why not use the same solution in your service worker?
That's what I did for my blog - Django's static file manager adds the correct URLs https://jakearchibald.com/sw.js

here's a simple Node script that will create the array of filenames for you, provided you want a list of every file in your web/public directory. NOTE: you want to run this from a terminal at your public directory.
var fs = require('fs');
var path = require('path');
var util = require('util');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var i = 0;
(function next() {
var file = list[i++];
if (!file) return done(null, results);
//file = dir + '/' + file;
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
next();
});
}
else {
file = file.replace('/home/ubuntu/workspace/public', '');
results.push(file);
next();
}
});
})();
});
};
var mydir = path.resolve(__dirname);
walk(mydir, function(err, results) {
if (err) throw err;
console.log(util.inspect(results, { maxArrayLength: null }));
});

I was experiencing some issues with this, with a vue3 pwa.
So this is not a true answer, but rather a hopefully valuable reply.
With vue3, the service worker file that is generated, includes:
importScripts(
"/precache-manifest.\<something-something\>.js"
);
and the precache-manifest.js file that is generated, lists all the js, css and font stuff that is built when doing a "vue-cli-serve build", e.g. something like:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "f715169493da60af08a445c4f7990905",
"url": "/.htaccess"
},
{
"revision": "87260e830ed912c46685c0a5432addf2",
"url": "/.well-known/web-app-origin-association"
},
<snip>
The workbox script then takes this list and caches the mentioned files.

Related

How to resolve path issues while moving files in node.js?

I am trying to get a file from html form and store it in another folder. It's basically cloud function, and I am new to both node.js and firebase so don't know what I am doing wrong. What I manage to do is:
const fileMiddleware = require('express-multipart-file-parser');
app.post("/sendMail", (req, res) => {
const {
fieldname,
filename,
encoding,
mimetype,
buffer,
} = req.files[0];
console.log(req.files[0].originalname);
var fs = require('fs')
var oldPath = req.files[0].originalname;
var newPath = '/functions/'+oldPath;
fs.rename(oldPath, newPath, function (err) {
if (err) throw err
console.log('Successfully renamed - AKA moved!')
});
});
Whenever I try to move file, I got path issues. The error is as follows:
[Error: ENOENT: no such file or directory, rename 'C:\Users\Maisum Abbas\now\functions\sendMail.txt'
> 'C:\functions\sendMail.txt'] {
> errno: -4058,
> code: 'ENOENT',
> syscall: 'rename',
> path: 'C:\\Users\\Maisum Abbas\\now\\functions\\sendMail.txt',
> dest: 'C:\\functions\\sendMail.txt'
> }
Also, this is the path where I want to actually move the file but oldpath is already setup like this.
C:\Users\Maisum Abbas\now\functions\sendMail.txt
Since I needed to attach a file with email, it was causing path issues. I tried it with multer and it works. What I did:
//call libraries here
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, 'resume/');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('filetoupload');
app.post("/careerMail", (req, res) => {
const { name } = req.body;
const { email } = req.body;
const { phone } = req.body;
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
});
const dest = 'mymail';
const mailOptions = {
from: email, // Something like: Jane Doe <janedoe#gmail.com>
to: dest,
subject: 'Candidate Application', // email subject
html: `<div>
<strong>From:</strong> ` +
name +
`<br /><br />
<strong>Email:</strong> ` +
email +
`<br /><br />
<strong>Phone:</strong> ` +
phone +
`<br /><br />
</div>
`,// email content in HTML
attachments: [
{
filename: req.files[0].originalname,
content: req.files[0].buffer.toString("base64"),
encoding: "base64"
}
]
and rest of the code...
I suggest rethinking this approach altogether. You won't be able to move files around in a deployed function. The nodejs runtime filesystem doesn't allow any files to be written anywhere in the filesystem, except for os.tmpdir() (which is /tmp on Linux).
If you need to write a file temporarily, you should definitely only use that tmp space. Be aware that files written there occupy memory and should be deleted before the function terminates, or you could leak memory.
You can read files that you deployed with your code, but you should do that through relative paths.
I ran into same problem while moving file. I sort this problem by using a function to get the application root folder and then concatenate rest of the location.
//place this file on application root.
//import where you need to get the root path.
const path = require('path');
module.exports = (function(){
return path.dirname(require.main.filename || process.mainModule.filename);
})();
//taking your case move location.
const rootPath = //require the above module.
const newPath = rootPath + /functions/' +oldPath;
fs.rename(oldPath, newPath, function (err) {
if (err) throw err
console.log('Successfully renamed - AKA moved!')
});

Nodejs Not able to create directory

I want to post an image to server.But before that I want to make sure that directory is create, before placing an image to a correct folder.The folder that I want to create is year/month/day/[image]. I am able to generate the folder on my local PC, but when I want to apply on the server, an error message is displayed and the folder is not created.I don't know what mistake that I have made, I hope someone can help me solve this problem.
Thank you in advance.
PWD
ERROR
return binding.mkdir(pathModule._makeLong(path), Error: ENOENT: no
such file or directory, mkdir
'/home/eis/development/eis-api-dev/picture/2020/06/01/'
CODE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
///output: home/eis/development/eis-api-dev/picture/2020/06/01/
const dir = path.join(__dirname,_const.IMAGE_FILE_PATH+_const.generateImagePath(null,null,null));
console.log("path:"+dir);
fs.exists(dir,exists =>{
if(!exists){
//mkdirp.sync(dir);
return fs.mkdirSync(dir,{recursive: true},error => cb(error,dir));
}
return cb(null,dir)
});
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
try to create using mkdirp
if (!fs.existsSync(directoryPath)){
mkdirp(directoryPath, function (err) {
if (err) {
console.log("Error Creating Directory "+directoryPath);
}
else {
console.log("Creating Directory "+directoryPath);
}
}
I just have to upgraded latest nodejs version and its worked.
To create a directory asynchronously
const fs = require('fs');
const path = 'newfolder/xyz/';
fs.exists(path, exists => {
if (exists) {
console.log('The directory exists...!!');
}
else {
fs.mkdir(path, { recursive: true }, (error) => {
console.log(error);
if (error)
// print or display your error
else {
return path;
}
});
}
});

Error using fastify-multer to upload images

I am trying to use the fastify-multer plugin to upload files to the server and I am able to successfully get the images uploaded to the folder.
The problem is my app crashes.
I used the fastify-cli generated structure and I am running it as a standalone server as mentioned in the README.md here.
I am writing it as a fastify plugin.
"use strict";
const fp = require("fastify-plugin");
module.exports = fp(function(fastify, opts, next) {
fastify.decorate("uploadImage", function(request) {
const path = require("path");
const multer = require("fastify-multer");
var storage = multer.diskStorage({
destination: path.join(path.join(__dirname + "/uploads/")),
filename: function(request, file, cb) {
cb(null, file.originalname);
}
});
var upload = multer({ storage }).single("myImage");
upload(request, function(err) {
if (err) {
console.log(err);
} else {
console.log("Saved...");
return { saved: true };
}
});
});
next();
});
And here is the error I get :
Hi looked into your issue. You are using fastify-multer in the wrong way.
Invoking multer({ storage }).single("myImage") you are creating a fastify's preHandler hook that accepts 3 specific parameters. You can find more on the offical documentation. A simple working example could be the one you can see at fastify-multer:
const server = fastify()
// register fastify content parser
server.register(multer.contentParser)
server.route({
method: 'POST',
url: '/profile',
preHandler: upload.single('avatar'),
handler: function(request, reply) {
// request.file is the `avatar` file
// request.body will hold the text fields, if there were any
reply.code(200).send('SUCCESS')
}
})
If you need more help just provide me a repro repo on github and I'll try to figure out what is the best solution for your case.
Let me know! :)

Moved route from app.js to route.js and app no longer works

In my app.js file I had the code below and it worked as intended. I need to clean up my code, so I moved it to it's own route at routes/random and it no longer works because I get an error that states: "http://localhost:1337/random/1/1/testing 404 (Not Found)" and I am not sure why. My original code was in my app.js file when it was working was:
app.get('/random/:room/:userId/:message', function(req, res) {
fs.appendFile(room.number.toString(), req.params.message, function(err) {
if (err) {
console.log('error writing messages to file');
};
fs.readFile('./' + room.number, 'utf-8', function(err, data) {
if (err) {
if (err.fileNotFound) {
return this.sendErrorMessage('can\'t find the file, you linked it incorrectly');
}
console.log('error reading message file');
};
if (req.params.userId == 1) {
messages.user1.push(data);
} else {
messages.user2.push(data);
};
console.log(messages);
res.send(data);
fs.unlink(req.params.room, function(err) {
});
});
});
});
the new code includes the following for app.js
var express = require('express');
var app = express();
var fs = require('fs');
var random = require('./routes/random');
app.use('/random/', random);
app.use(express.static('public'));
app.use(express.static('public/js'));
app.use(express.static('public/images'));
and after I moved it, the route code is:
var express = require ('express');
var fs = require ('fs');
var random = express.Router();
random.get('/random/:room/:userId/:message', function(req, res) {
fs.appendFile(room.number.toString(), req.params.message, function(err) {
if (err) {
console.log('error writing messages to file');
};
fs.readFile('./' + room.number, 'utf-8', function(err, data) {
if (err) {
if (err.fileNotFound) {
return this.sendErrorMessage('can\'t find the file, you linked it incorrectly');
}
console.log('error reading message file');
};
if (req.params.userId == 1) {
messages.user1.push(data);
} else {
messages.user2.push(data);
};
console.log(messages);
res.send(data);
fs.unlink(req.params.room, function(err) {
});
});
});
});
module.exports = random;
Can anyone explain what I have done wrong that won't allow it to find the file?
In your code you are defining a route called random\random... in random.js, delete first random there, because middleware(app.use..) will direct all routes with /random to your router instance.
Your router is handling a url that starts with /random, and you attach this to your app under the path /random/. Remove one or the other (preferebly, the one inside the router).
I was able to fix it. Both comments above are correct, but it still was throwing errors due to my variables being undefined. I figured it out though so I am closing this question. Thank you both

Node.js EXDEV rename error

I've been playing with some code I found in a book about Node.js. It is a simple app which uploads images.
It shows the EXDEV error (500 Error: EXDEV, rename).
Could someone give me a hint? Here's my code:
exports.submit = function(dir) {
return function(req, res, next) {
var img = req.files.photo.image;
var name = req.body.photo.name || img.name;
var path = join(dir, img.name);
fs.rename(img.path, path, function (err) {
if(err) return next(err);
Photo.create({
name: name,
path: img.name
}, function (err) {
if(err) return next(err);
res.redirect('/');
});
});
};
};
Renaming files cannot be done cross-device. My guess is that your upload directory (which by default is /tmp) is on another partition/drive as your target directory (contained in the dir variable).
Some solutions:
configure the upload directory to be on the same partition/drive as your target directory; this depends on which module you're using to handle file uploads, express.bodyParser (and the module it uses, connect.multipart) accepts an uploadDir option that you can use;
before starting your Node app, set the TMPDIR environment variable to point to a temporary directory on the same partition/drive as your target directory. If you're using a Unix-type OS:
env TMPDIR=/path/to/directory node app.js
instead of setting the environment variable from your shell, set it at the top of your Node app:
process.env.TMPDIR = '/path/to/directory';
instead of renaming, use a module like mv that can work cross-device;
Using Windows XP, I added to app.js:
process.env.TMPDIR = '.'; //new

Categories

Resources