Unable to resolve this, I am not sure why its coming.
boot.ts
"use strict";
import {bootstrap} from '../angular2/platform/browser';
import {appComponent} from '../components/app/appComponent';
bootstrap(appComponent);
appComponent.ts
'use strict'
import {Component} from '../../angular2/core';
#Component({
selector: 'app',
templateUrl: 'components/app/app.html'
})
export class appComponent {
message:string='Hello html';
}
and in HTML file
<script>
System.config({
defaultJSExtensions: true,
packages: {
app: {
defaultExtension: 'js'
}
}
});
System.import('components/boot').then(null, console.error.bind(console));
</script>
and stack trace
I saw that you use relative path for angular2 modules. Perhaps you could try something like this:
'use strict'; // <------------
import {bootstrap} from 'angular2/platform/browser';
import {appComponent} from '../components/app/appComponent';
bootstrap(appComponent);
and
'use strict';
import {Component} from 'angular2/core'; // <------------
#Component({
selector: 'app',
templateUrl: 'components/app/app.html'
})
export class appComponent {
message:string='Hello html';
}
You need to include Angular2 dist like this into your HTML file:
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
(...)
Hope it helps you,
Thierry
Related
I am using react as the client side and node.js as the server side, and using webpack to transpile. When I start the website on local host it is missing all of its styling and css. Any Ideas?
This is my frontend webpack that handles the transpiling of my frontend code
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
target: 'node',
externals: [nodeExternals()],
entry: './frontend/src/App',
output: {
path: path.resolve(__dirname, 'backend/build'),
filename: 'bundle.js',
libraryTarget: 'commonjs2',
libraryExport: 'default'
},
module: {
rules: [
{
test: /\.jsx$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}
},
{
test: /\.css$/,
use: [ 'css-loader'],
sideEffects: true
}
]
}
};
This is my backend/server.js that handles server rendering
const express = require('express');
const React = require('react');
const { renderToString } = require('react-dom/server');
const App = require('../backend/build/bundle');
const { matchPath } = require('react-router-dom');
const app = express();
// This is the middleware that will handle all routes
app.get('*', (req, res) => {
// We create a context object that will be passed to the StaticRouter
const context = {};
// Render the app component to a string
const html = renderToString(
React.createElement(App, {
location: req.url,
context,
})
);
// If the app component set a context.url value, it means the user
// tried to access a protected route that they are not authenticated for.
// In this case, we redirect them to the login page.
if (context.url) {
res.redirect(context.url);
} else {
// Send the rendered HTML as the response
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<div id="root">${html}</div>
<script src="/build/bundle.js"></script>
</body>
</html>
`);
}
});
app.listen(3000, () =\> {
console.log('Server is listening on port 3000');
});
This is my frontend App.js
import React from "react";
import { StaticRouter } from "react-router-dom/server";
import { Footer, Contact, Who, Header } from "./containers";
import { Navbar, Background } from "./components";
import { Route, Routes } from "react-router-dom";
import "./App.css";
const App = (props) =\> {
return (
\<StaticRouter location={props.location} context={props.context}\>
\<Navbar /\>
\<Routes\>
\<Route exact path="/" element={\<Header /\>} /\>
\<Route path="/about" element={\<Who /\>} /\>
\<Route path="/contact" element={\<Contact /\>} /\>
\</Routes\>
\<Footer /\>
\</StaticRouter\>
);
};
export default App;
And this is my index.js
import React from 'react';
import ReactDom from 'react-dom';
import './index.css';
import App from './App';
ReactDom.render(
\<BrowserRouter\>
\<App /\>
\</BrowserRouter\>,
document.getElementById('root')
)
I have tried to add the styling-loader to the webpack config for the frontend but I end up getting an error where the document is not defined. The routing works fine, just no css or images, just basic html is being rendered`
I have been trying to learn how to SSR with React(without using Next.js) I've gotten to the point that I'm seeing the HTML rendered on the page but once I add the css imports to style the component babel start throwing errors (
C:\Users\Frozen\Desktop\ssr stuff\ssr4\src\App.css:1
body {
^
SyntaxError: Unexpected token '{'
)
.babelrc
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
}
webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './build'),
filename: "bundle.js",
publicPath: "/"
},
devServer: {
port: 3010,
static: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['#babel/preset-env', "#babel/preset-react"]
}
},
},
{
test: /\.(css|scss)$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
publicPath: "/"
})
]
};
server.js
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './src/App.js';
import path from 'path';
import fs from 'fs';
const app = express();
app.get('/', (req, res) => {
console.log('in /');
fs.readFile(
path.resolve('./build/index.html'),
'utf8',
(err, data) => {
if (err) {
console.log(err);
return res.status(500).send('Internal Server Error');
}
const html = data.replace(
'<div id="root"></div>',
`<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`
)
console.log(html)
return res.send(html);
}
);
});
app.use(express.static(path.resolve(__dirname,'build')));
app.listen(3000, () => {
console.log('server listening on port 3000')
})
I also fail to understand why do I have to put the app.use(static) below the app.get('/') aren't middlewares supposed to go one after another in order top to bottom (if I move the app.use(static) above the app.get('/') where I return the component I don't see the console.log('in /');
index.js
import React from "react";
import ReactDOM from 'react-dom'
import App from "./App";
const appElement = document.getElementById('root');
ReactDOM.hydrate(<App/>, appElement)
I run
npx webpack
npx babel-node server.js
And I get the css error (if I remove the css import I don't get it but I don't have css in the component)
Also is there a way to rebuild and run server.js once I change something ( like when you use create-react-app ) Also any other suggestions on what I can improve in the current setup will be much appreciated.
Install babel-plugin-css-modules-transform npm install --save-dev babel-plugin-css-modules-transform.Then include it in .babelrc "plugins": ["css-modules-transform"]
I have a ReactJS project with Node/Express serving my server. On my front end (React) is serving port 3312 and on my server it's serving port (5000). When I load my front end through port 3312, everything looks great and my react router routes works fine. (My api's work everything is great). However, when I try and serve static files and see if I get the same result through my server (port 5000) I only see the styles on my page. (I have a background color) I don't see any of the html whatsoever that the static files should be serving?
I get no errors in the console when I look at localhost:5000. However, my css styles are displaying on the page correctly (cause I have a background color set on my body). However, I cannot see any of my front end React displaying html code. I went inside my index.html file and put a simple test in the root div and it's displaying but I don't understand why my React code isn't displaying on my server.
I most likely think the problem is with the express static files not serving my images or React Router code. I should also note that I'm not using create-react-app I'm using webpack dev server react no cli.
Also, I'm not using create-react-app I'm using no cli for custom webpack.
Here is my code:
(Node Server)
const express = require("express");
const path = require("path");
const router = express.Router();
const app = express();
const port = 5000;
// Serve static files on server
app.use("/public", express.static(__dirname + "/../public"));
app.get("*", function(request, response) {
response.sendFile(path.join(__dirname + "/../public/index.html"));
});
if (app.get("env") === "development") {
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
} else {
app.listen(port, "171.33.4.126", () => {
console.log(`Server started on port ${port}`);
});
}
routes.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import HomePage from "./components/homepage";
import AboutPage from "./components/aboutpage";
import Contactpage from "./components/contactpage";
export default (
<Router>
<div>
<Switch>
<Route exact path="/" component={Landingpage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={Contactpage} />
</Switch>
</div>
</Router>
);
index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Routes from "./routes";
ReactDOM.render(<div>{Routes}</div>, document.getElementById("root"));
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link
href="/public/assets/css/styles.css"
rel="stylesheet"
type="text/css"
/>
<title>Site</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
Webpack Configuration Development
const webpack = require("webpack");
const path = require("path");
// const HtmlWebPackPlugin = require("html-webpack-plugin");
const BrowserSyncPlugin = require("browser-sync-webpack-plugin");
module.exports = {
devServer: {
historyApiFallback: true,
port: 3312,
proxy: {
"/api": "http://localhost:5000"
}
},
entry: ["babel-polyfill", __dirname + "/src/index.js"],
output: {
path: path.join(__dirname, "/public"),
filename: "bundle.js",
publicPath: "/"
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: ["react", "env", "stage-0"]
}
}
},
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
}
]
},
plugins: [
// new HtmlWebPackPlugin({
// template: "./public/index.html"
// }),
new BrowserSyncPlugin({
host: "localhost",
port: 3312,
files: [
"./public/*.html",
"./public/assets/scss/*.scss",
"./public/assets/variables/*.scss",
"./public/assets/mixins/*.scss",
"./public/assets/reset/*.scss"
],
proxy: "http://localhost:3312/"
})
]
};
Here is a screenshot of my folder structure:
Screenshot of network status in console:
Your react code is not showing up because index.html is not including it. Is public/bundle.js your transpiled react code? If so, add the following line to index.html, right after <div id="root"></div>:
<script src="/public/bundle.js"></script>
If not, then change the path pointed by src to the correct one.
You can see your css styles just fine because you are already including those in index.html.
UPDATE: a couple of points based on your webpack config:
Change the port in which you are running webpack-dev-server to 3000. You will also have to change BrowserSyncPlugin's proxy to http://localhost:3000/. You can then go to localhost:3312 in your browser and requests will be proxied to the webpack-dev-server running on port 3000.
Correct me if I'm wrong, but you have not posted your index.html in its entirety. I'm guessing you already have a line that looks like <script src="/bundle.js"></script> somewhere in that .html file -- based on your latest comment, it seems it is being added by HtmlWebPackPlugin. webpack-dev-server is serving bundle.js through /, the publicPath you've specified in webpack's output option. This works just fine as long as you access your site through localhost:3312 or localhost:3000. However, your express.js server running on port 5000 has no idea webpack-dev-server is serving bundle.js at /; as a result of that, you end up seeing none of your react code when you go to localhost:5000. As for the styles, you are already serving them correctly through /public/assets/css, which the express.js server understands because you've specified that in this line: app.use("/public", express.static(__dirname + "/../public")). The solution is to change the line <script src="/bundle.js"></script> in your .html file to:
<script src="http://localhost:3312/bundle.js"></script>
Also, in webpack's output option, change the publicPath to http://localhost:3312/. Now, as long as you have webpack-dev-server running (with BrowserSyncPlugin), you can access
your site at localhost:5000 and your bundle.js file should be
served just fine.
Try the following:
Webpack Config
module.exports = {
devServer: {
contentBase: path.join(__dirname, "/public"),
historyApiFallback: true,
port: 3000,
proxy: {
"/api": "http://localhost:5000"
}
},
entry: ["babel-polyfill", __dirname + "/src/index.js"],
output: {
path: path.join(__dirname, "/public"),
filename: "bundle.js",
publicPath: "http://localhost:3312/"
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: ["react", "env", "stage-0"]
}
}
},
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
}
]
},
plugins: [
new BrowserSyncPlugin({
host: "localhost",
port: 3312,
files: [
"./public/*.html",
"./public/assets/scss/*.scss",
"./public/assets/variables/*.scss",
"./public/assets/mixins/*.scss",
"./public/assets/reset/*.scss"
],
proxy: "http://localhost:3000/"
})
]
};
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link
href="/assets/css/styles.css"
rel="stylesheet"
type="text/css"
/>
<title>Site</title>
</head>
<body>
<div id="root"></div>
<script src="http://localhost:3312/bundle.js"></script>
</body>
</html>
Oh sorry, it looks like the problem is in index.js. Change {Routes} to <Routes />
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Routes from "./routes";
ReactDOM.render(<div><Routes/></div>, document.getElementById("root"));
You have another problem in routes.js. Export a component like
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import HomePage from "./components/homepage";
import AboutPage from "./components/aboutpage";
import Contactpage from "./components/contactpage";
// make this a component
export default ()=>(
<Router>
<Switch>
<Route exact path="/" component={Landingpage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={Contactpage} />
</Switch>
</Router>
);
I am creating an application using angular5 and express 4.16. I have anchor tag on home page on click of which another component should be rendered (it should be redirected to that URL) but only URL changes.
Required code is below.
app-routing.module.ts
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AppComponent } from './app.component';
import { TestComponent } from '../test/test.component';
const routes: Routes = [
{ path: '', redirectTo: '/', pathMatch: 'full' },
{ path: 'Test', component: TestComponent }
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
app.component.ts
import { Component } from '#angular/core';
// Import the DataService
import { DataService } from './data.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Define a users property to hold our user data
employees: Array<any>;
// Create an instance of the DataService through dependency injection
constructor(private _dataService: DataService) {
// Access the Data Service's getUsers() method we defined
this._dataService.getEmployees()
.subscribe(res => this.employees = res);
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import {TestComponent } from '../test/test.component';
import { AppRoutingModule } from './app-routing.module';
import{DataService} from './data.service'
import {HttpModule} from '#angular/http'
#NgModule({
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
HttpModule
],
declarations: [
AppComponent,
TestComponent
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
out put of folder through ng build /dist/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>IndexV3</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<test-html></test-html>
<script type="text/javascript" src="inline.bundle.js"></script>
<script type="text/javascript" src="polyfills.bundle.js"></script>
<script type="text/javascript" src="styles.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
</html>
Node/Express server.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
// API file for interacting with MongoDB
const api = require('./server/routes/api');
// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
// API location
app.use('/api', api);
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
//Set Port
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`Running on localhost:${port}`));
Output of home page as desired
Downoad screenshot Output after running localhost:3000 as desired anchor tag rendered
After click on anchor tag url changed but test component didnt rendered on browser
Downoad screenshot
test.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'test-html',
templateUrl: './test.component.html'
})
export class TestComponent {
title = 'app';
}
app.component.html
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
</h1>
</div>
<a [routerLink]="['/Test']" >test</a>
<ul>
<li *ngFor="let employee of employees">{{employee.name}}</li>
</ul>
test.component.html
<span>yeeee</span>
Project Structure
download project structure if required
You are missing the router-outlet. Take the template you have for app.component and create a new component with that template. Then make your app.component.html contain only
<router-outlet></router-outlet>
Then in your app.routing.module.ts replace the object for your home route with:
{ path: '', component: YourNewHomeComponent },
more about router-outlet: https://angular.io/guide/router#router-outlet
I'm having a problem using the Angular2 router and express, but none of the previous questions seem to have the solution I need. I'm using the latest version of the angular2-cli.
When I direct my browser to localhost:3000, I get the generic "app works" message that the angular2-cli generates. My problem arises when I try to navigate to one of my child routes, such as localhost:3000/auth/login - it redirects me back to the same "app works" page, instead of showing me a page that says "login works".
Looking at other questions on stack exchange, I figure that the issue is here:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
When I replace the * with a /, instead of redirecting me back to my target page, it gives me the cannot GET error.
In summary, my problem is that url navigation of my angular2 routes integrated into my express app is not working.
My express code in server.js is as follows:
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var mongoose = require("mongoose");
var path = require("path");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(express.static(path.join(__dirname, 'dist')));
// Catch all other routes and return the index file
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.listen(3000, () => {
console.log("Server has started");
});
My application's routing module is as follows (app-routing.module.ts):
import {Route, RouterModule} from '#angular/router';
import {NgModule} from '#angular/core';
import {LoginComponent} from './login/login.component';
import {RegisterComponent} from './register/register.component';
import {FeedComponent} from './feed/feed.component';
import {FindComponent} from './find/find.component';
import {SubmitComponent} from './submit/submit.component';
import {ProfileComponent} from './profile/profile.component';
export const routeConfig = [
{
path: "auth",
children: [
{
path: "login",
component: LoginComponent
},
{
path: "register",
component: RegisterComponent
},
{
path: "",
redirectTo: "/login",
pathMatch: "full"
}
]
},
{
path: "app",
children: [
{
path: "feed",
component: FeedComponent
},
{
path: "find",
component: FindComponent
},
{
path: "submit",
component: SubmitComponent
},
{
path: "profile",
component: ProfileComponent
},
{
path: "",
redirectTo: "/feed",
pathMatch: "full"
}
]
}
];
#NgModule({
imports: [RouterModule.forRoot(routeConfig)],
exports: [RouterModule]
})
export class AppRoutingModule{
}
My application module is as follows:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import {AppRoutingModule} from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { FeedComponent } from './feed/feed.component';
import { FindComponent } from './find/find.component';
import { SubmitComponent } from './submit/submit.component';
import { ProfileComponent } from './profile/profile.component';
#NgModule({
declarations: [
AppComponent,
LoginComponent,
RegisterComponent,
FeedComponent,
FindComponent,
SubmitComponent,
ProfileComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
All the components have been defined in their respective files and are the barebones default templates generated by the angular2-cli.
I have no idea what to do at this point. I've even tried restarting and rewriting this project multiple times to see if I went wrong somewhere (this is my 3rd attempt).
For angular2 and nodejs integration you can either put this in server.js:
var cors = required('cors');
app.use(cors());
or you can make use of proxy in your web server. For example in apache2 inside virtualhost tag you can do
ProxyPass /api/ http://localhost:3000/
ProxyReverse /api/ http://localhost:3000/
Now instead of using "http://localhost:3000/" in your http request function (although you are not using it) you can use just "api/".