Angular2 XHR error(404 Not Found) while loading main.js - node.js

I use gulp to watch typescript files and I store translated .js files in public/js. Whenever I start my project, angular2 doesn't work, because of this error:
Cannot get main.js
Here is the Error that I'm getting.
system.config.js
(function (global) {
System.config({
paths: {
'npm:': 'node_modules/'
},
map: {
app: 'public/js',
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
packages: {
app: {
main: './main',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
index.ejs
(I'm using express and all files below are loaded correctly).
<head>
<title>Chat room</title>
<link rel="stylesheet" href="/css/index.css">
<script src="/systemjslib/system.src.js"></script>
<script src="/systemjsconf"></script>
<script src="/shimlib/shim.min.js"></script>
<script src="/zonelib/zone.js"></script>
<script src="/rxjslib/Reflect.js"></script>
</head>
<body>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
<my-app>Loading AppComponent content here ...</my-app>
</body>
main.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var platform_browser_dynamic_1 = require("#angular/platform-browser-dynamic");
var app_module_1 = require("./app.module");
platform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule);
Project files structure
I would really appreciate some help. Thanks in advance. If I missed out some files that are important, let me know I will edit this post, I really need this fixed.

Related

How setup react-helmet with Server Side Rendering?

I've been trying to setup react-helmet with server-side-rendering. I followed the docs and some blog posts on how to setup react-helmet with SSR, but have been unable to produce the desired results. Here's a code snippet of how I'm rendering the App:
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './src/App';
const express = require('express');
const app = express();
app.get('*', (req, res) => {
const app = renderToString(<App />);
const helmet = Helmet.renderStatic();
res.send(formatHTML(app, helmet));
})
function formatHTML(appStr, helmet) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
</head>
<body>
<div id="root">
${ appStr }
</div>
<script src="./bundle.js"></script>
</body>
</html>
`
}
When I run the above code, I get an error saying 'cannot use import statement outside a module'. Is it possible to use both es5 and es6 syntax at the same time? Or is there is better way to setup React-helmet?
This is my babel configuration file
{
"presets": [
[
"#babel/preset-env",
{
"modules": false
}
],
"#babel/preset-react",
"#babel/preset-flow"
],
"env": {
"development": {
"only": [
"app",
"internals/scripts"
],
"plugins": [
"#babel/plugin-transform-react-jsx-source"
]
},
"production": {
"only": [
"app"
],
"plugins": [
"transform-react-remove-prop-types",
"#babel/plugin-transform-react-constant-elements",
"#babel/plugin-transform-react-inline-elements"
]
},
"test": {
"plugins": [
"#babel/plugin-transform-modules-commonjs",
"dynamic-import-node"
]
}
},
"compact": true,
"plugins": [
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-syntax-import-meta",
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-json-strings",
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"#babel/plugin-proposal-function-sent",
"#babel/plugin-proposal-export-namespace-from",
"#babel/plugin-proposal-numeric-separator",
"#babel/plugin-proposal-throw-expressions",
"#babel/plugin-proposal-export-default-from",
"#babel/plugin-proposal-logical-assignment-operators",
"#babel/plugin-proposal-optional-chaining",
[
"#babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/plugin-proposal-do-expressions",
"#babel/plugin-proposal-function-bind",
"lodash"
]
}
You need to wrap your server using #babel/register.
This is how I handle that for my TypeScript CRA projects without ejecting.
NOTICE: I use this method to inject metadata into index.html vs render the whole app (some components I use don’t play well with SSR).
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js
"use strict"
require("ignore-styles")
require("#babel/register")({
ignore: [/(node_modules)/],
presets: [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-typescript",
],
extensions: [".tsx"],
cache: false,
})
require("./server")
server.js (excerpt)
const indexPath = path.join(__dirname, "build/index.html")
const middleware = async (req, res, next) => {
let context = {}
let html = renderToString(
React.createElement(StaticRouter, {
location: req.url,
context: context,
})
)
const helmet = Helmet.renderStatic()
if (context.url) {
res.redirect(context.url)
} else if (!fs.existsSync(indexPath)) {
next("Site is updating... please reload page in a few minutes.")
} else {
let index = fs.readFileSync(indexPath, "utf8")
let status = 200
if (typeof context.status === "number") {
status = context.status
}
return res.status(status).send(
index
.replace('<div id="root"></div>', `<div id="root">${html}</div>`)
.replace("</head>", `${helmet.meta.toString()}</head>`)
.replace("</head>", `${helmet.title.toString()}</head>`)
.replace("</head>", `${helmet.script.toString()}</head>`)
)
}
}
server.get("/", middleware)
server.use(express.static(path.join(__dirname, "build")))
server.get("*", middleware)

"Target container is not a DOM element." When Running Webpack server

I have recently switched from using 'npm start' script that comes with create-react-app to Weback's 'npm run build' and then running the server. After slowly getting all the dependencies working I got my bundle to complete building. However, when I use 'npm start' the server starts and nothing shows up on my website.
I tried inputting <div id="root"> into my .html file in my "public" directory, but it didn't work. I then found out Webpack created a second for me? Either way placing a <div> or even a <script> in either one doesn't work.
I have updated all of my dependencies for react so that the ReactDOM could render peacefully. my React code worked perfectly before I switched to webpack so I'm sure it's not a problem with my index.js and whatever it imports.
I'm convinced it's a problem in webpack, but I've tried plenty of different presets in webpack.config.js and can't seem to find any that works (I have forgotten the ones I've tried so I will take any suggestions).
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: './main.js',
path: path.resolve(__dirname, '/dist')
},
plugins: [new webpack.ProgressPlugin(), new HtmlWebpackPlugin(), new webpack.IgnorePlugin(/^pg-native$/)],
module: {
rules: [
{
test: /.(js|jsx)$/,
include: [path.resolve(__dirname, 'src')],
loader: 'babel-loader',
options: {
plugins: [
'syntax-dynamic-import'
],
presets: [
'#babel/preset-env',
'#babel/preset-react',
{
'plugins': ['#babel/plugin-proposal-class-properties']
}
]
}
},
{
test:/\.(s*)css$/,
use:['style-loader','css-loader', 'sass-loader']
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
loader: 'url-loader?limit=100000'
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},
chunks: 'async',
minChunks: 1,
minSize: 30000,
name: true
}
},
node: {
fs: 'empty'
}
,
devServer: {
open: true
}
};
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import App from './App.js';
import * as serviceWorker from './serviceWorker';
let state = {};
window.setState = (changes) => {
state = Object.assign({}, state, changes);
ReactDOM.render(
<App {...state}/>,
document.getElementById('root')
);
}
/* eslint no-restricted-globals: 0*/
let initialState = {
name: 'Name Test',
location: location.pathname.replace(/^\/?|\/$/g, "")
};
window.setState(initialState);
serviceWorker.unregister();
<!-- .HTML created by Webpack -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
<!-- .HTML created by create-react-app (before webpack)-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Skedge</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
when I go into the web console this shows up as an error -
Uncaught Invariant Violation: Target container is not a DOM element.
at invariant (webpack:///./node_modules/react-dom/cjs/reactdom.development.js?:55:15)
at Object.render (webpack:///./node_modules/react-dom/cjs/reactdom.development.js?:21151:36)
at eval (webpack:///./src/index.js?:35:50)
at Module../src/index.js (http://localhost:8080/main.js:3970:1)
at webpack_require (http://localhost:8080/main.js:20:30)
at eval (webpack:///multi_(webpack)-dev-server/client?:2:18)
at Object.0 (http://localhost:8080/main.js:4015:1)
at webpack_require (http://localhost:8080/main.js:20:30)
at http://localhost:8080/main.js:84:18
at http://localhost:8080/main.js:87:10
It says it doesn't understand the ReactDOM.render() function.
I even threw in a <h1>Test</h1> to see if it was my code but it still bugged out, so I'm sure it's something in my webpack.config.js that isn't right but I just can't figure out what.
Edit
I gave up on using webpack, I undid my npm eject and went back to just using npm start.

Why do I get "TypeError: Reflect.getOwnMetadata is not a function"

I'm working on File Upload with Angular2 and Node.js with ng2-File-Upload
but while running my project i got an error related to Reflect.getOwnMetadata
here is the error shown :
and here is my systemjs.config.js
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
/** Path for ng2-file-upload */
'ng2-file-upload' : 'npm:ng2-file-upload'
/** Path for ng2-file-upload */
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './transpiled-js/main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
},
/** Configuration for ng2-file-upload */
'ng2-file-upload' : {
main: './ng2-file-upload.js',
defaultExtension: 'js'
}
/** Configuration for ng2-file-upload */
}
});
})(this);
This is the scenario when I faced the exact same issue:
I had two TypeScript files with the same name (say, FileUploadService.ts) residing in two different locations. One was for handling server logic (residing in a server directory), and the other in a public directory for file upload through an Angular service.
The problem was that I was importing the wrong service in a location where the ng2-file-upload package was used, which in turn depends on Angular modules - which were never being imported.
This meant that the file where Reflect.getOwnMetadata is defined somewhere was unavailable during the Typescript compilation.
Please make sure you reference the correct file in the correct location which might be the case for you too.

systemjs not able to load my module

systemjs.config.js:
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
'mystartup_commons': 'npm:mystartup_commons'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
mystartup_commons: {
defaultExtension: 'js'
}
}
});
})(this);
This is the index.js it is pointing to:
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./helpers"));
__export(require("./model2"));
Error in browser :
GET
http://localhost:3000/node_modules/mystartup_commons/dist/src/helpers
404 (Not Found)
GET
http://localhost:3000/node_modules/mystartup_commons/dist/src/helpers
404 (Not Found)
You are pointing mystartup_commons to a file, not a package. Thus the defaultExtension doesn't have much effect.
Try jspm and it will show you how to get things setup.
This issue may also "interest" you as you are working with TS and SystemJS:
https://github.com/systemjs/systemjs/issues/1587

Making grunt-mocha works with requirejs

Running the following Mocha tests in a browser works, but when I use grunt mocha in the command line, I get Warning: PhantomJS timed out. I have turned the gruntfile mocha.options.run to false, because, if true, the requirejs do not have the time to run.
Sadly, I cannot find any complete sample on the matter.
the gruntfile contains:
mocha: {
test: {
src: ['tests/index.html']
},
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Mocha Test</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" type="text/css" charset="utf-8" />
</head>
<body>
<div id="mocha"></div>
<script src="../node_modules/mocha/mocha.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
mocha.setup('bdd');
</script>
<script src="../node_modules/chai/chai.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var expect = chai.expect;
</script>
<script data-main="requireRunner.js" src="../vendor/require-2.1.9.js"></script>
</body>
</html>
requireRunner:
require.config({
baseUrl: '/',
paths: {
'jquery' : '../vendor/jquery-2.0.3',
'underscore' : '../vendor/underscore-1.5.2',
'backbone' : '../vendor/backbone-1.1.0'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
}
},
urlArgs: 'bust=' + (new Date()).getTime()
});
require([
'tests/models/todoTest'
], mocha.run
);
todoTest
define(['js/models/todo'], function(Todo) {
describe('Todo', function(){
var todo;
before(function() {
todo = new Todo();
})
it('defaults are ok', function(){
expect(todo.get('title')).to.equal('');
expect(todo.get('completed')).to.be.false;
})
})
})
todo
/*global define*/
define([
'underscore',
'backbone'
], function (_, Backbone) {
'use strict';
var TodoModel = Backbone.Model.extend({
// Default attributes for the todo
// and ensure that each todo created has `title` and `completed` keys.
defaults: {
title: '',
completed: false
}
});
return TodoModel;
});
Multiple little things to make it work properly:
paths seem to be more tolerant on the browser, path problem can occur only on grunt-mocha (this is not a problem, just a reminder)
running grunt mocha is not enough, grunt server mocha is the way, a server has to be up
using options:{log: true} combined with requirejs debugging traces in the index.html is good help
Your post has helped me to set up my grunt-mocha task ! Thx
I had de turn false the mocha.options.run, otherwise grunt-mocha handled no tests (guess requirejs had not time to load as you said)
however I did not have to set up any server to make it works.
Running grunt mocha is plenty enough !
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FdP - Tests</title>
<link rel="stylesheet" href="../app/vendor/mocha/mocha.css"/>
</head>
<body>
<div id="mocha"></div>
<script src="../app/vendor/mocha/mocha.js"></script>
<script src="../app/vendor/chai/chai.js"></script>
<script>
mocha.setup('bdd');
chai.should();
</script>
<script data-main="specRunner.js" src="../app/vendor/requirejs/require.js"></script>
</body>
</html>
my mocha task
mocha: {
test: {
src: ['test/index.html']
}
}
specRunner.js
...
function (testSuite) {
'use strict';
require(testSuite.specs, function () {
mocha.run();
});
...
Grunt-mocha version : 0.4.7
I think may be there is some files include error in you test html file. you can go to folder of your html file, double click the file, if test case can run normally in browser, then grunt-mocha can run it too. So, maybe the problem is something like require.js not found.

Resources