Module Federation Not working with dynamic hooking the remote in webpack.config.js - webpack-module-federation

I have module federation setup and working fine when I load the remotes upfront in index.html
Below works
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://localhost:8002/remoteEntry.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
host webpack
{
name: "home",
library: {type: "var", name: "home"},
filename: "remoteEntry.js",
remotes: {
nav: "dashboards",
},
shared: ["react", "react-dom"],
}
remote webpack
{
name: "dashboards",
library: {type: "var", name: "dashboards"},
filename: "remoteEntry.js",
remotes: {},
exposes: {
Header: "./src/Header",
},
shared: ["react", "react-dom"],
}
However this loads the JS File upfront which is undesireable. I was following examples where the library is dynamically loaded in webpack... Here is what I want to do
index.html
<!DOCTYPE html>
<html lang="en">
<body>
<div id="root"></div>
</body>
</html>
host webpack
{
name: "app-shell",
filename: "remoteEntry.js",
remotes: {
dashboards: "dashboards#http://localhost:8002/remoteEntry.js",
},
}
remote webpack
{
name: "dashboards",
filename: "remoteEntry.js",
remotes: {},
exposes: {
Header: "./src/Header.jsx",
},
}
I get error on the host app
Uncaught syntax error; Invalid or unexpected token:
module.exports = dashboards#http://localhost:8002/dist/remoteEntry.js;

You're Remote Webpack exposes object is incorrect. You're missing the ./ in front of Header. Replace with this:
"./Header": "./src/Header.jsx"
Also, if that doesn't work, try removing the library section:
library: {type: "var", name: "dashboards"}
I think this changes the remoteType from var to script, which apparently helps.

Related

Next-AUTH UNTRUST_HOST_ERROR on AWS Amplify

Deployed NextJS app on AWS Amplify
I am getting untrust host in my CloudWatch logs.
Can someone help?
[next-auth][error][UNTRUST_HOST_ERROR]
URL: https://master.dtzbr8sfj0q7k.amplifyapp.com/
I have added this domain in my Cognito allowed callbacks.
package.json
"next": "13.0.7",
"next-auth": "^4.18.6",
Build Settings
version: 1
applications:
- frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
- COGNITO_CLIENT_ID=${COGNITO_CLIENT_ID}
- COGNITO_CLIENT_SECRET=${COGNITO_CLIENT_SECRET}
- COGNITO_DOMAIN=${COGNITO_DOMAIN}
- JWT_SECRET=${JWT_SECRET}
- NEXTAUTH_URL=${NEXTAUTH_URL}
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
appRoot: client
/pages/api/[...nextauth].js
import NextAuth from "next-auth/next";
function CognitoProvider(options) {
return {
id: "cognito",
name: "Cognito",
type: "oauth",
wellKnown: `${options.issuer}/.well-known/openid-configuration`,
idToken: true,
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
};
},
options,
};
}
export default NextAuth({
providers: [
CognitoProvider({
clientId: process.env.COGNITO_CLIENT_ID,
clientSecret: process.env.COGNITO_CLIENT_SECRET,
issuer: process.env.COGNITO_DOMAIN,
}),
],
secret: process.env.JWT_SECRET,
callbacks: {
jwt({ token, account, profile }) {
if (account) {
console.log("Account exists");
// modify token
token.role = profile["cognito:groups"];
}
return token;
},
session({ session, token }) {
if (session.user) {
// modify session
session.user.roles = token.role;
}
return session;
},
},
});
/index.js
import Head from "next/head";
import App from "../components/App/App";
import { useSession, signIn, signOut } from "next-auth/react";
export default function Home() {
const { data: session } = useSession();
if (session) {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<App />
</>
);
}
return (
<>
Not signed in <br />
<button
onClick={() => {
e.preventDefault();
signIn("cognito", {
callbackUrl: process.env.NEXTAUTH_URL,
});
}}
>
Sign in
</button>
</>
);
}
Any Help would be appreciated
I had the same problem today and I found this solution that worked for me:
I had to edit the amplify.yml in build settings and set env variables inside a .env file as below:
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- echo "NEXTAUTH_URL=$NEXTAUTH_URL" >> .env
- echo "JWT_SECRET=$JWT_SECRET" >> .env
- npm run build
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
I had to do it for all of my environment variables to allow my Next.js application to access them.
Hope it helped.
Make sure you have configured NEXTAUTH_URL environment variable correctly on AWS Amplify.
I checked your website, and I see this error:
CLIENT_FETCH_ERROR
On NextAuth.js documentation,
Here's a similar case:
How to solve client fetch error for next-auth authentication
Update
Sorry for the late reply. These links might give you a little more information about the issue.
Similiar Case
Environment Variables User Guide on AWS Amplify

HTML returned from Lambda#Edge and CloudFront throws JSON is not parsable

I'm trying to set up a reverse proxy on a subfolder of our domain (example.com/sub) to show content from a site sitting on a different domain/server. I would like to access that site on the same domain subfolder for SEO purposes.
I have a CloudFront distribution set up for the whole domain. On the same distribution, I have an additional behavior /sub* Viewer request linked to a Lambda#Edge function.
In that lambda function, I'm returning some HTML. For testing, I'm using code straight from AWS docs.
'use strict';
const content = `
<\!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Lambda#Edge Static Content Response</title>
</head>
<body>
<p>Hello from Lambda#Edge!</p>
</body>
</html>
`;
exports.handler = (event, context, callback) => {
/*
* Generate HTTP OK response using 200 status code with HTML body.
*/
const response = {
status: '200',
statusDescription: 'OK',
headers: {
'cache-control': [{
key: 'Cache-Control',
value: 'max-age=100'
}],
'content-type': [{
key: 'Content-Type',
value: 'text/html'
}]
},
body: content,
};
callback(null, response);
};
This works as expected. But when I try to return a more complex HTML for example
exports.handler = async (event, context, callback) => {
console.log(event);
const response = await fetch('https://www.nbcnewyork.com');
const content = await response.text();
const res = {
status: '200',
statusDescription: 'OK',
headers: {
'cache-control': [{
key: 'Cache-Control',
value: 'max-age=100'
}],
'content-type': [{
key: 'Content-Type',
value: 'text/html'
}]
},
body: content,
};
callback(null, res);
};
When I GET the example.com/sub I'm getting the error below.
502 ERROR
The request could not be satisfied.
The Lambda function returned invalid JSON: The JSON output is not parsable. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
Generated by cloudfront (CloudFront)
Request ID: *
In CloudWatch for CloudFront/LambdaEdge I'm also seeing these events:
2022-04-08T12:31:50.000+02:00 (2k-5BGOaTxD_Ll51dVhJbBRN0rQY4yjju4k9TEPQcpgzl1MZa-vYAA==) INFO START processing EventType: viewer-request LambdaFunctionARN: arn:aws:lambda:eu-central-1:*:1 Method: GET URI: /sub
2022-04-08T12:31:50.000+02:00 (2k-5BGOaTxD_Ll51dVhJbBRN0rQY4yjju4k9TEPQcpgzl1MZa-vYAA==) INFO Invoking LambdaFunctionARN: arn:aws:lambda:eu-central-1:*:1 Region: eu-central-1
2022-04-08T12:31:50.000+02:00 (2k-5BGOaTxD_Ll51dVhJbBRN0rQY4yjju4k9TEPQcpgzl1MZa-vYAA==) INFO Response received from Lambda: RequestId: *
2022-04-08T12:31:50.000+02:00 (2k-5BGOaTxD_Ll51dVhJbBRN0rQY4yjju4k9TEPQcpgzl1MZa-vYAA==) ERROR Validation error: The Lambda function returned an invalid json output, json is not parsable.
2022-04-08T12:31:50.000+02:00 (2k-5BGOaTxD_Ll51dVhJbBRN0rQY4yjju4k9TEPQcpgzl1MZa-vYAA==) INFO END processing EventType: viewer-request LambdaFunctionARN: arn:aws:lambda:eu-central-1:*:f
Any ideas about what I'm doing wrong?
Regards, Primoz

Webpack Build Can't Find CSS or JS Bundles

When trying to run my build script for the first time, I noticed that while the files were created, if I try to open the index.html file in the build directory it can't find any of the CSS or JS bundle files, even though they're in the build directory. Here's my webpack.config:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const extractSass = new ExtractTextPlugin({
filename: '[name].[contenthash].css',
disable: process.env.NODE_ENV === 'development'
});
const VENDOR_LIBS = [
'react',
'react-dom',
'react-router',
'react-router-dom'
];
module.exports = {
entry: {
bundle: ['babel-polyfill', './src/index.js'],
vendor: VENDOR_LIBS
},
output: {
path: path.join(__dirname, 'build'),
publicPath: '/',
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: [path.resolve(__dirname, 'src')],
query: {
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0', 'react']
}
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract([
'css-loader',
'postcss-loader',
'sass-loader'
])
},
{
test: /\.png$/,
use: [
{
loader: 'url-loader',
options: { limit: 40000 }
},
{
loader: 'image-webpack-loader',
query: { bypassOnDebug: true }
}
]
}
]
},
devServer: {
historyApiFallback: true
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [autoprefixer]
}
}),
extractSass
]
};
And my index.html file in the build folder:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-
scale=1">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="/bundle.9e0f7c3719625da97504e3ec5c2054db.css" rel="stylesheet"></head>
<body>
<div id="entry"></div>
<script type="text/javascript" src="/manifest.a2844a6ed8a5cd15d1a5.js"></script>
<script type="text/javascript" src="/vendor.14bbb1b3abf7a67a5307.js"></script>
<script type="text/javascript" src="/bundle.1ef0a652c0808bca139d.js">
</script></body>
</html>
The error I get in the browser dev tools is Failed to Load Resource for each of my 3 JS bundle files and my 1 CSS file. If I remove the "/" in front of each of the filenames in the index.html file, those errors go away but then I get another error that it can't find a specific .png file in the build, which is also in the build folder.
I'm using webpack 2.6.1
If I can provide any further info please let me know - kinda new at asking questions here.
Change your webpack config to:
module.exports = {
output: {
publicPath: ''
}
}

Delete DynamoDB entries with AWS API

I am learning AWS API Gateway to manage the api in the cloud and not through express.js. I created the method DELETE under a resource with the following Integration Request.
Integration Request
Integration Type: AWS Service
AWS Region: us-east-1
AWS Service: DynamoDB
HTTP method: DELETE
Action: deleteItem
Execution role: XXXXXX
Content Handling: Passthrough
the execution role is working because i can read/write to DynamoDB. a Body Mapping Template that has a Content-Type: application/json as follows:
{
"TableName": "comments",
"Key": {
"commentId": {
"S": "$context.requestId"
},
"pageId": {
"S": "$input.path('$.pageId')"
},
"userName": {
"S": "$input.path('$.userName')"
}
}
}
when i try to run the test with a Request Body as follows:
{
"pageId": "breaking-news-story-01-18-2016",
"userName": "cacevedo"
}
I get the following information:
Request: /comments
Status: 200
Latency: 80 ms
Response Body
Response Body:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html
xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head>
<title>Page Not Found</title> </head> <body>Page Not Found</body>
</html>
Can someone help me out with this, because i am not able to delete the item. yet it seems that the integration request is working. Am i missing something or doing something wrong?
Just in case anyone runs into the same problem. the HTTP verb needs to be a post and not delete and also is case sensitive so instead of using deleteItem. use DeleteItem

JWPlayer mp3 Captions in Playlist

I'm using JWPlayer v6.8.4616..
When i test it with a Single audio/mp3 file, with Caption, it works. For example:
<script type='text/javascript'>
jwplayer("theplayer").setup({
file: "http://www.example.com/audio1.mp3",
tracks: [{
file: "http://www.example.com/audio1.srt"
}]
});
</script>
The Audio/mp3 file is playing along with Caption on it.
But when i test with the Playlist, the Captions are shown only on the Video Tracks, but not on the Audio/mp3 Tracks.
Like:
<script type='text/javascript'>
jwplayer("theplayer").setup({
playlist: [{
file: "http://www.example.com/video1.mp4",
title: "Video Track (1)",
tracks: [{
file: "http://www.example.com/video1.srt",
label: "English",
kind: "captions",
"default": true
}]
},{
file: "http://www.example.com/video2.mp4",
title: "Video Track (2)",
tracks: [{
file: "http://www.example.com/video2.srt",
label: "English",
kind: "captions",
"default": true
}]
},{
file: "http://www.example.com/audio1.mp3",
title: "Audio Track (1)",
tracks: [{
file: "http://www.example.com/audio1.srt",
label: "English",
kind: "captions",
"default": true
}]
}]
});
</script>
Why is it and how to have Captions on the Audio/mp3 Tracks in the Playlist, please?