Firebase deployng Sapper app as cloud function failed - javascript

The problem
I'm building Sapper SSR app that loads content from Firebase storage based on data required from Firebase realtime database. My app is deployed on Firebase cloud functions. But last time I deployed I got this error, since last deploy I implemented loading some data from realtime database and other minor features, so I don't know what is causing this error.
Deploy command:
/usr/bin/node /usr/local/lib/node_modules/npm/bin/npm-cli.js run deploy:functions --scripts-prepend-node-path=auto
> violette-website#0.0.1 deploy:functions /home/hejtmus/Documents/Websites/Violette/sapper/Violette/functions
> firebase deploy --only functions:ssr
=== Deploying to 'violette-77756'...
i deploying functions
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔ functions: required API cloudbuild.googleapis.com is enabled
✔ functions: required API cloudfunctions.googleapis.com is enabled
i functions: preparing functions directory for uploading...
i functions: packaged functions (4.41 MB) for uploading
✔ functions: functions folder uploaded successfully
i functions: current functions in project: ssr(us-central1)
i functions: uploading functions in project: ssr(us-central1)
i functions: updating Node.js 12 function ssr(us-central1)...
⚠ functions[ssr(us-central1)]: Deployment error.
Function failed on loading user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs
Functions deploy had errors with the following functions:
ssr
To try redeploying those functions, run:
firebase deploy --only "functions:ssr"
To continue deploying other features (such as database), run:
firebase deploy --except functions
Error: Functions did not deploy properly.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! violette-website#0.0.1 deploy:functions: `firebase deploy --only functions:ssr`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the violette-website#0.0.1 deploy:functions script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/hejtmus/.npm/_logs/2020-09-27T18_34_13_296Z-debug.log
Process finished with exit code 1
Firebase logs:
Error: function terminated. Recommended action: inspect logs for termination reason. Function cannot be initialized.
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{"code":3,"message":"Function failed on loading user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs"},"authenticationInfo":{"principalEmail":"filip.holcik.official#gmail.com"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/violette-77756/locations/us-central1/functions/ssr"}
What I tried
I tried:
running app in dev mode, works perfect
building app as js function, works perfect
serving app via firebase serve, works perfect
deploying app using firebase deploy or firebase deploy --only functions, none of them works, throws above specified error
checking code for errors and misconfiguration, found nothing
I tried solving this problem with knowledge from this article, I followed this tutorial form step to step, but I still got the same error:
https://blog.logrocket.com/build-an-ssr-web-app-with-firebase-functions-hosting-and-svelte-sapper/
I tried also removing code I added and deployng app without loading data from firebase realtime database, but it didn't help.
Code:
index.js (cloud functions):
const functions = require('firebase-functions');
const { sapperServer } = require('./__sapper__/build/server/server');
exports.ssr = functions.https.onRequest(sapperServer);
server.js:
import sirv from 'sirv';
import express from 'express';
import compression from 'compression';
import * as sapper from '#sapper/server';
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
const sapperServer = express()
.use(
compression({ threshold: 0 }),
sirv(`static`, { dev }),
sapper.middleware()
)
if(dev){
sapperServer.listen(PORT, err => {
if (err) console.log('error', err);
});
}
export { sapperServer }
I will provide more info if needed.

What was the problem
The problem was, that I used firebase for browser, Svelte is compiler an it runs in Node.js environment, it has to be bundled by code bundler (I use rollup). To be able to run firebase in node, just specify mainFields in rollup configuration.
resolve({
browser: true,
dedupe: ['svelte'],
mainFields: ['main']
}),
I use firebase only in client, so there is no need to specify mainFields parameter in server in my case.
Full rollup configuration
import resolve from '#rollup/plugin-node-resolve';
import replace from '#rollup/plugin-replace';
import commonjs from '#rollup/plugin-commonjs';
import svelte from 'rollup-plugin-svelte';
import postcss from 'rollup-plugin-postcss';
import autoPreprocess from "svelte-preprocess";
import pluginJson from "#rollup/plugin-json";
import babel from 'rollup-plugin-babel';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup.js';
import pkg from './package.json';
const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]#sapper[/\\]/.test(warning.message)) || onwarn(warning);
const preprocessOptions = {
postcss: {
plugins: [
require('postcss-import'),
require('postcss-preset-env')({
stage: 0,
browsers: 'last 2 versions',
autoprefixer: { grid: true }
})
]
}
};
export default {
client: {
input: config.client.input(),
output: config.client.output(),
plugins: [
replace({
'process.browser': true,
'process.env.NODE_ENV': JSON.stringify(mode)
}),
svelte({
preprocess: autoPreprocess(preprocessOptions),
dev,
hydratable: true,
emitCss: true,
css: css => {
css.write('static/css/bundle.css');
}
}),
postcss({
extract: "static/css/imported.min.css",
sourceMap: true,
minimize: true,
}),
resolve({
browser: true,
dedupe: ['svelte'],
mainFields: ['main']
}),
commonjs(),
legacy && babel({
extensions: ['.js', '.mjs', '.html', '.svelte'],
runtimeHelpers: true,
exclude: ['node_modules/#babel/**'],
presets: [
['#babel/preset-env', {
targets: '> 0.25%, not dead'
}]
],
plugins: [
'#babel/plugin-syntax-dynamic-import',
['#babel/plugin-transform-runtime', {
useESModules: true
}]
]
}),
!dev && terser({
module: true
})
],
onwarn,
},
server: {
input: config.server.input(),
output: config.server.output(),
plugins: [
replace({
'process.browser': false,
'process.env.NODE_ENV': JSON.stringify(mode)
}),
svelte({
preprocess: autoPreprocess(preprocessOptions),
generate: 'ssr',
dev,
css: css => {
css.write('static/css/bundle.css');
}
}),
postcss({
extract: "static/css/imported.min.css",
sourceMap: true,
minimize: true,
}),
resolve({
dedupe: ['svelte']
}),
commonjs(),
pluginJson(),
],
external: Object.keys(pkg.dependencies).concat(
require('module').builtinModules || Object.keys(process.binding('natives'))
),
onwarn,
},
serviceworker: {
input: config.serviceworker.input(),
output: config.serviceworker.output(),
plugins: [
resolve(),
replace({
'process.browser': true,
'process.env.NODE_ENV': JSON.stringify(mode)
}),
commonjs(),
!dev && terser()
],
onwarn,
}
};

Related

Vue app has compilation error when serve is run from jest-playwright-preset, but works fine otherwise

I'm trying to test a vue.js application with playwright.
If I start the mocked server with npm run serve:mock from the command line, then run playwright using npm run test:playwright (jest -c jest-playwright.config.js), everything works fine.
If I try to combine both and have the server start from jest-playwright-preset (jest-process-manager), I get compilation errors when the development server starts:
Module parse failed: Unexpected token (139:76) File was processed with
these loaders: * ./node_modules/cache-loader/dist/cjs.js *
./node_modules/babel-loader/lib/index.js *
./node_modules/eslint-loader/index.js You may need an additional
loader to handle the result of these loaders.
This is the jest-playwright.config.js:
module.exports = {
rootDir: '.',
testTimeout: 120000,
testMatch: ['<rootDir>/tests/playwright/*.spec.js'],
preset: 'jest-playwright-preset',
testEnvironmentOptions: {
'jest-playwright': {
launchOptions: {
headless: false
},
contextOptions: {
ignoreHTTPSErrors: true,
bypassCSP: true
},
browsers: ['chromium', 'firefox']
}
},
serverOptions: {
command: 'npm run serve:mock',
launchTimeout: 50000,
port: 8080,
debug: true
}
};
Why is there a difference, and how can I fix it?

Svelte app shows blank page on first start

This my first time running a Svelte app and I have this issue where the app doesn't seem to know where build/build.css and build/build.js are.
I got the same issue when I tried Svelte with Tailwind.
This is my config when I created the project:
import svelte from 'rollup-plugin-svelte';
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import css from 'rollup-plugin-css-only';
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
This is the ouput after running npm start:
Here is my folder structure:
What went wrong?
This looks very much like the official Svelte template. In this case, the command to build, watch, & serve is npm run dev.
npm start just runs the web server and serve existing files. You'd use it, for example to test your prod build after npm run build.

If running webpack programmatically he doesn't find module

I want to use webpack-api at my electron app for build external web project.
I decide using webpack API in my app, but webpack can't found the babel-loader.
I created simple repository to reproduce the error: repository
Abstract presentation of the project (A - electron app, B - web project for build)
Error msg:
main.js:1 Uncaught Error: Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module 'D:\User\B\node_modules\babel-loader\lib\index.js'
at eval (webpack:///./node_modules/loader-runner/lib_lazy_namespace_object?:5)
at eval (main.js:1)
Base structure of both project:
Project A:
- main.js
- node_modules/
- webpack.config.js
Project B:
- main.js
- node_modules/
- webpack.config.js
Every project is independent and has all tool for development(like webpack)
My webpack config in project A for run webpack (if I using '/' in path I get API Schema error at webpack):
module.exports = {
mode: "development",
target: "web",
entry: "D:\\User\\B\\src\\main.js",
context: "D:\\User\\B\\",
output: {
path: "D:\\A",
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.(js)$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
resolve: {
modules: [
'D:\\User\\B\\node_modules', //the same error if remove this line
],
},
stats: {
errorDetails: true
},
}
Run webpack:
const webpack = require('webpack');
const config = require('./webpack.config');
const compiler = webpack(config);
compiler.run((err, stats) => {
//output errors...
});
Important:
If to try build project B using webpack cli (through npm), no
errors.
Project A based on Electron.
Using library version on both project: babel-loader^8.1.0, #babel/core^7.9.0, webpack^4.42.1, electron^8.2.1(electron only at A project)
Bundle file is created
Bundle js file is using in HTML file
Looks like this server already has other webpack wich running in watch mode and constanlty removing packages. Try to reload the server

"Serverless-offline: route not found." running an AWS Lambda function in offline mode

This question is pretty much the same as Serverless offline not getting route, but since that one was not answered I'm asking again. I'm trying to follow this article, https://medium.com/#awesome1888/how-to-use-serverless-locally-with-webpack-and-docker-5e268f71715, on how to deploy a Lambda function with Serverless.
I have a directory with the following structure:
> tree -I node_modules
.
├── package-lock.json
├── package.json
├── serverless.yml
├── src
│   ├── handler.js
│   └── index.js
└── webpack.config.js
where serverless.yml reads
service: my-first-lambda
plugins:
- serverless-webpack
- serverless-offline
provider:
name: aws
runtime: nodejs10.x
region: us-east-1
stage: dev
functions:
hello:
handler: src/handler.main
events:
- http:
path: /hello
method: any
custom:
webpack:
includeModules: true
src/index.js reads
import moment from 'moment';
const handler = async (event, context) => {
const body = await new Promise((resolve) => {
setTimeout(() => {
resolve(`Hello, this is your lambda speaking. Today is ${moment().format('dddd')}`)
}, 2000);
});
return {
statusCode: 200,
body,
};
}
export default handler;
src/handler.js reads
export { default as main } from './index';
and webpack.config.js reads
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const slsw = require("serverless-webpack");
module.exports = {
entry: slsw.lib.entries,
target: "node",
mode: slsw.lib.webpack.isLocal ? "development" : "production",
externals: [nodeExternals()],
output: {
libraryTarget: "commonjs",
path: path.join(__dirname, ".webpack"),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
plugins: ["#babel/plugin-proposal-object-rest-spread"]
}
}
]
}
]
}
};
The problem is when I start up the function in offline mode, it seems to have only one very specific route:
>
npx serverless offline start --region us-east-1 --noTimeout --port 3000 --host 0.0.0.0
Serverless: Bundling with Webpack...
Time: 1203ms
Built at: 08/30/2019 2:35:10 PM
Asset Size Chunks Chunk Names
src/handler.js 6.81 KiB src/handler [emitted] src/handler
Entrypoint src/handler = src/handler.js
[./src/handler.js] 42 bytes {src/handler} [built]
[./src/index.js] 1.64 KiB {src/handler} [built]
[moment] external "moment" 42 bytes {src/handler} [built]
Serverless: Watching for changes...
Serverless: Starting Offline: dev/us-east-1.
Serverless: Routes for hello:
Serverless: POST /{apiVersion}/functions/my-first-lambda-dev-hello/invocations
Serverless: Offline [HTTP] listening on http://0.0.0.0:3000
Serverless: Enter "rp" to replay the last request
and if I go to http://localhost:3000/hello, I get this response:
{"statusCode":404,"error":"Serverless-offline: route not found.","currentRoute":"get - /hello","existingRoutes":["post - /{apiVersion}/functions/my-first-lambda-dev-hello/invocations"]}
Any idea why this is not working? (I've perused https://serverless.com/framework/docs/ but couldn't quickly find an answer).
I had this issue and if anyone comes across it, this github comment fixed my issue.
You can run $ sls offline start --noPrependStageInUrl or add the following to your serverless.yml file
custom:
serverless-offline:
noPrependStageInUrl: true
According to the comment:
I had this problem with anything 6+, this was due to the fact that it now defaults to appending the staging name to the url path. To revert to the old way, you need to add --noPrependStageInUrl to the cli or in the serverless file custom: serverless-offline noPrependStageInUrl: true to revert to previous setting. I'm testing it his out but #dherault the functionality is not reflecting what is actually happening in AWS.
I was using serverless-offline: "6.7.0" and my index.handler was as below:
const serverless = require("serverless-http");
const express = require("express");
const app = express();
app.get("/", function (req, res) {
res.send("Hello World!");
});
module.exports.handler = serverless(app);
And my serverless.yml
plugins:
- serverless-offline
custom:
serverless-offline:
noPrependStageInUrl: true
provider:
name: aws
runtime: nodejs12.x
stage: dev
region: eu-west-2
functions:
app:
handler: src/index.handler
events:
- http: ANY /
- http: "ANY {proxy+}"
Apologies this isn't exactly a great answer but hopefully, someone comes across this and it is a solution to their problem.
Looks like you've got a whitespace issue in your serverless.yml file.
Try indenting path and method under the http block:
functions:
hello:
handler: src/handler.main
events:
- http:
path: /hello
method: any
for setup a quick example using serverless template :
sls create -h
output :
create ........................ Create new Serverless service
--template / -t .................... Template for the service. Available templates: "aws-clojure-gradle", "aws-clojurescript-gradle", "aws-nodejs", "aws-nodejs-typescript", "aws-alexa-typescript", "aws-nodejs-ecma-script", "aws-python", "aws-python3", "aws-groovy-gradle", "aws-java-maven", "aws-java-gradle", "aws-kotlin-jvm-maven", "aws-kotlin-jvm-gradle", "aws-kotlin-nodejs-gradle", "aws-scala-sbt", "aws-csharp", "aws-fsharp", "aws-go", "aws-go-dep", "aws-go-mod", "aws-ruby", "aws-provided", "azure-nodejs", "cloudflare-workers", "cloudflare-workers-enterprise", "cloudflare-workers-rust", "fn-nodejs", "fn-go", "google-nodejs", "google-python", "google-go", "kubeless-python", "kubeless-nodejs", "openwhisk-java-maven", "openwhisk-nodejs", "openwhisk-php", "openwhisk-python", "openwhisk-ruby", "openwhisk-swift", "spotinst-nodejs", "spotinst-python", "spotinst-ruby", "spotinst-java8", "plugin" and "hello-world"
step1: so for generated a new nodejs example with an api :
sls create -t aws-nodejs-ecma-script -n service-name-hello-world
step2: install serverless-offline :
npm install serverless-offline -D
step3: in serverless.yml
plugins:
- serverless-webpack
- serverless-offline
step4 : start local server
serverless offline start -r us-west-1 --stage dev
github Example
git clone https://github.com/ysfmag/aws-serverless-nodejs-example
cd aws-serverless-nodejs-example
yarn
yarn start
serverless.yml
to define an api in your serverless framework you need to respect yaml format , and in the path variable you dont need to start with '/hello' just 'hello' will work .
functions:
hello:
handler: src/handler.main
events:
- http:
path: hello
method: get

How to configure firebase-admin sdk

~Hello, I'm developing a user control system with google firebase.
Only 2 functions for the moment: add users and remove them.
For add a user is so easy, I only need to copy and paste the autogenerated script from the console, but the problem here is delete a user because I need admin-level auth for this, so, I've reading about node.js and I have a VPS running on Centos7, so I proceeded whith the instalation:
yum install npm
Then in the folder of my domain I used the following:
npm init
For generate the initial package.json:
npm install firebase-admin --save
And then I had no idea how to use it, since I understand that the function require is not defined for browsers since it is backend, I mean for the following error in the browser:
Uncaught ReferenceError: require is not defined
Reading a bit more I found that I can use something called webpack (the first time I use it) and I followed the next instructions:
npm install --save-dev ts-loader webpack-node-externals
npm install --global webpack
Then, my configuration files:
webpack.config.js
'use strict';
var nodeExternals = require('webpack-node-externals');
module.exports = {
entry: './index.ts',
output: {
filename: 'index.js',
libraryTarget: 'this'
},
target: 'node',
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true
}
}
]
},
resolve: {
extensions: [ '.ts', '.tsx', '.js' ]
},
externals: [nodeExternals()]
};
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "./",
"noImplicitAny": true,
"strictNullChecks": false
},
"include": [
"./*.ts"
],
"exclude": [
"node_modules"
]
}
index.ts
const admin = require('firebase-admin');
const serviceWorker = require('./<MY_PRIVATE_KEY>.json');
admin.initializeApp({
credential: admin.credential.cert(serviceWorker),
databaseURL: "https://<MY_DATABASE>.firebaseio.com/"
});
and after running the webpack command, is generated the index.js file that should be included in my website... but the problem is... I still have a error... (complete error in the attached image)
Error of my website in the generated index.js
So...
I would appreciate if you help me solve the error... I'm a new in node.js
I only want to run the delete user function:
admin.auth().deleteUser(uid)
.then(function() {
alert("Successfully deleted user");
})
.catch(function(error) {
alert("Error deleting user:" + error);
});

Categories