Aurelia-http-client 404 not found - jspm

I am trying to follow this tutorial but I am having import issues for aurelia-http-client.js.
Overview:
Working in Visual Studio Asp.Net 5 project. Through jspm I installed aurelia-framework and aurelia-bootstrapper.
jspm install aurelia-framework
jspm install aurelia-bootstrapper
I wanted my app.js to be included in a different folder than my root so:
<div aurelia-app>
<script src="~/jspm_packages/system.js"></script>
<script src="~/config.js"></script>
<script>
System.config({
"paths": {
"*": "js/aurelia/*.js"
}
});
System.import("aurelia-bootstrapper");
</script>
</div>
Now all seems fine it load app.js from the proper folder. I now need to use the aurelia-router so:
import {Router} from "aurelia-router";
export class App {
static inject() { return [Router]; }
constructor(router) {
this.router = router;
this.router.configure(config => {
config.title = "Reddit";
config.map([
{route: ["", "funny"], moduleId: "funny", nav: true, title: "Funny Subreddit"},
{route: "gifs", moduleId: "gifs", nav: true, title: "Gifs Subreddit"}
]);
});
}
}
There is where it blows up...I believe router is trying to grab aurelia http client because my console throws up with a 404 -> http://localhost:53342/js/aurelia/aurelia-http-client.js...Which I am curious why its looking in /js/aurelia for aurelia-http-client in the first place.

I thought aurelia-framework included aurelia-http-client it did not. jspm install aurelia-http-client did the trick.

There seems to be a new version of skeleton navigation template for ASP.NET 5...
System.js is usually configured via separate config.js file. Here's the one from skeleton application. Note that it also has paths for jspm packages:
paths: {
"*": "js/aurelia/*",
"github:*": "jspm_packages/github/*",
"npm:*": "jspm_packages/npm/*"
}
You might need to correct those paths to be relative to your application root.

Related

Is it possible to use webpack with a library that uses dependency injection?

I'm pretty new to webpack so apologies if this is an obvious answer. I'm currently trying to deploy a typescript lambda api to AWS using this library: https://www.npmjs.com/package/ts-lambda-api
The library uses Inversify for dependency injection: https://github.com/inversify/InversifyJS
The library also advises building by just using zip but I'd like to use webpack if I can.
I currently have two files for my api, a main api.ts file and then a controller.ts file. Currently the api class finds the controllers using the same lines as in the ts-lambda-api docs:
const controllersPath = [path.join(__dirname, "controllers")]
const app = new ApiLambdaApp(controllersPath, appConfig)
As a result I need the controller directory to be available to the api.ts class once it's been bundled. Currently my webpack config looks like this:
import path = require('path')
import webpack = require('webpack')
const config: webpack.Configuration = {
module: {
rules: [
{ test: /\.js\.map$/, use: "ignore-loader" },
{ test: /\.d\.ts$/, use: "ignore-loader" }
]
},
mode: 'production',
entry: {
my_api: ['./src/my-api.js'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]/main.js',
library: '[name]',
libraryTarget: 'commonjs2'
},
target: 'node',
externals: [/aws-sdk.*/, 'aws-lambda']
};
export default config
How can I add to it to allow my api access to the other classes it needs? The webpack docs have a page on multiple entry points (https://webpack.js.org/concepts/entry-points/#multi-page-application) but that doesn't seem to be what I'm looking for as it gives me multiple bundles.
I can put multiple files into one bundle by doing something like:
api: ['./src/api.js','./src/controllers/controller.js],
Although this won't then work with the Injectable annotations. Anyone have any other ideas?
I managed to get around this issue by manually loading in the controllers following the section in the ts-lambda-api docs on how to do so.

Angular +Workbox = build ChunkLoadError: Loading chunk # and Refused to execute script because its MIME

I have added Workbox to Angular in first production deploy everything works fine, but after updating a module and rebuilding angular and injecting Workbox then visiting the site i see the service worker updates to the new version and refreshes the page, but now trying to use the updated module I get errors
Refused to execute script from 'https://example.com/8-es2015.203674bf0547eff7ff27.js'
because its MIME type ('text/html') is not executable,
and strict MIME type checking is enabled.
main-es2015.45ba4a512f87eefb1b3a.js:1 ERROR Error: Uncaught (in promise): ChunkLoadError:
Loading chunk 8 failed.(error: https://example.com/8-es2015.203674bf0547eff7ff27.js)
ChunkLoadError: Loading chunk 8 failed......
I looked at the network in chrome and I see that the file 8-es2015.203674bf0547eff7ff27.js is being served from the (disk cache) unlike the rest of the files which get served by (ServiceWorker), its content is the index.html file I don't know where it came from its not even part of the new build ? chrome places it in top frame section under scripts
Whats the reason for this Error, in the angular.json I have "outputHashing": "all", I delete everything and rebuild but still this errors, its until I clear the browser cash remove the ServiceWorker and hard refresh that the error stops happening until I reload page and it returns. Do I need to delete all the cache after every update, I thought Workbox does this automatically.Do I add something like so in the sw.js
self.addEventListener('activate', event => event.waitUntil(
caches.keys().then(cacheNames => cacheNames.forEach(name => caches.delete(name)))
)
);
Am using express, so I have set the maxAge on the sw.js to 0 and even change the public route to static files to a deep route but nothing
app.use('/sw.js', express.static(path.resolve('./public/dist/static/sw.js'), {maxAge: 0}));
app.use('/', express.static(path.resolve('./public/dist/static/'), {maxAge: 86400000}));
tools: angular 8.2.4 - workbox 4.3.1
Update
Removed workbox and the app worked, am guessing its cause of their new package workbox-window or the way am trying to use it. I have placed it in module service that is loaded from app.module then the service is called from a AppComponent ngOnInit. This could be the wrong way of initializing it.
code setup:
import {Workbox} from 'workbox-window';
#Injectable()
export class WorkerService {
supportWorker: boolean;
supportPush: boolean;
constructor(#Inject(WINDOW) private window: any, private loggerService: LoggerService) {
this.supportWorker = ('serviceWorker' in navigator);
this.supportPush = (this.supportWorker && 'PushManager' in window);
}
initWorker() {
if (this.supportWorker && environment.production) {
const wb = new Workbox('sw.js');
if (wb) {
wb.addEventListener('installed', event => {
if (event.isUpdate) {
// output a toast translated message to users
this.loggerService.info('App.webWorkerUpdate', 10000);
setTimeout(() => this.window.location.reload(), 10000);
}
});
wb.addEventListener('activated', event => {
if (!event.isUpdate) {
this.loggerService.success('App.webWorkerInit', 10000);
}
});
wb.register();
}
}
}
}
This the app component, i thought it would be best to add it to main.ts after bootstrapModule.then() but I don't know how inject a service in this method
#Component({
selector: 'app-root',
template: '<route-handler></route-handler>'
})
export class AppComponent implements OnInit {
constructor(private ws: WorkerService) {
}
ngOnInit(): void {
this.ws.initWorker();
}
}
After setting up Workbox in a different way it worked, the problem effected even chrome which failed to clear all cache after each build when testing it, had to use incognito to make sure everything works.
Here is the solution thanks to Ralph Schaer article a must read. His method is not to Cache-Bust the chunks angular build generates, also he globs in all the production scripts of workbox used by the app into the build folder and finally in the index.html he calls on workbox-window to register the service-worker.

nunjucks: Template not found

Trying to render a nunjucks template but getting Error: template not found: email.html.
server/
views/
email/
email.html
workers/
email.worker.js
//email.worker.js
function createMessage(articles) {
console.log(__dirname) // /<path>/server/workers
nunjucks.configure('../views/email/');
return nunjucks.render('email.html', articles);
}
No idea what's wrong here.
I had the same issue my solution was using path module:
const njk = require('nunjucks');
return njk.render(path.resolve(__dirname, '../views/email/' + 'email' + '.html'), articles);
I had same issue. I found this at the documentation:
In node, 'views' would be a path relative to the current working directory.
If you run the node server at the root directory, the template path would be server/views.
nunjucks.configure('server/views/email/');
return nunjucks.render('email.html', articles);
In my case, the server script is in public directory.
So, when i run the server from the root directory, the nunjucks configuration will look like this:
nunjucks.configure('src/templates');
return nunjucks.render('index.html', { name : 'Dian' });
It works.
But if I run the server from the public directory, the tempate will not found.
Had the same issue, try this if it helps. If you're using express and you have a views folder:
From nunjucks docs
var app = express();
nunjucks.configure('views', {
autoescape: true,
express: app
});
You can use nodejs' __dirname to resolve the path for you as
nunjucks.configure(__dirname + '/views')...
The nunjucks templates (located under src) were not included in build folder in my case.
Such a configuration in my nest-cli.json file solved my issue:
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "#nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": [
"**/*.njk"
]
}
}

Creating HapiJs server that can serve complex web pages

I have just started learning Node.js and hapi.js. What I am trying to accomplish now is build a REST web server that should also have a web interface for configuration and statistics collection.
I found that Inert plugin allows serving static pages and, as I understand, this limits me to loading a single web page that consists of a single file.
However, what I do not understand is whether it is possible to setup hapi.js to serve a full dynamic webpage with css, js and other files referenced within its body.
Am I heading the wrong direction with this or else how can I setup my scenario?
You can serve multiple static files from a specified directory.
Just tried out inert with hapi, using this example:
https://github.com/hapijs/inert#static-file-server
Inert has no problem serving multiple static files from a given directory, e.g public.
So you'll have no issue serving multiple static html, css, js files from a specified dir. You can then build a dynamic JSON api using Hapi, and have that consumed by your js client-side code, served from static js files in your public dir.
If you are needing templating, where you generate dynamic content on the serverside, hapi can do that out of the box, check out:
http://hapijs.com/tutorials/views
Sorry if this isn't what you mean, do feel free to clarify if not :-)
Hope that helps!
The vision plugin is used for templating, which is what I think you're after. If you want to bundle css and js files along with your pages, you can put them in a public directory and serve that with the inert plugin. And then you only need to reference the relative path in whatever html file you're trying to render.
Here's a simple example that uses handlebars. Inert is responsible for serving your css and js files while vision still renders your templates.
./index.js
var hapi = require('hapi');
var server = new hapi.Server();
server.connection({port: 5555});
server.register([require('vision'), require('inert')], (err) => {
if(err){
throw err;
}
server.views({
engines: {
html: require('handlebars')
},
relativeTo: __dirname + '/',
path: 'www'
});
var homeroute = {
method: 'GET',
path: '/',
handler: (request, reply) => {
reply.view('index', {name: 'cuthbert'});
}
};
var publicassetsroute = {
method: 'GET',
path: '/public/{param*}',
handler: {
directory: {
path: './public',
listing: false,
index: false
}
}
};
server.route(homeroute);
server.route(publicassetsroute);
server.start((err) => {
console.log('server started -- ' + server.info.uri)
});
});
www/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hapi Test</title>
<link rel="stylesheet" href="../public/index.css">
</head>
<body>
<h1>A Hapi Happy Test.</h1>
<p>This is a test page. Woo!</p>
<p>My name is {{name}}.</p>
</body>
</html>
public/index.css
p {
color: blue;
}

Using grunt server, how can I redirect all requests to root url?

I am building my first Angular.js application and I'm using Yeoman.
Yeoman uses Grunt to allow you to run a node.js connect server with the command 'grunt server'.
I'm running my angular application in html5 mode. According to the angular docs, this requires a modification of the server to redirect all requests to the root of the application (index.html), since angular apps are single page ajax applications.
"Using [html5] mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html)"
The problem that I'm trying to solve is detailed in this question.
How can I modify my grunt server to redirect all page requests to the index.html page?
First, using your command line, navigate to your directory with your gruntfile.
Type this in the CLI:
npm install --save-dev connect-modrewrite
At the top of your grunt file put this:
var modRewrite = require('connect-modrewrite');
Now the next part, you only want to add modRewrite into your connect:
modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']),
Here is a example of what my "connect" looks like inside my Gruntfile.js. You don't need to worry about my lrSnippet and my ssIncludes. The main thing you need is to just get the modRewrite in.
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
},
livereload: {
options: {
middleware: function (connect) {
return [
modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']),
lrSnippet,
ssInclude(yeomanConfig.app),
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app)
];
}
}
},
test: {
options: {
middleware: function (connect) {
return [
mountFolder(connect, '.tmp'),
mountFolder(connect, 'test')
];
}
}
},
dist: {
options: {
middleware: function (connect) {
return [
mountFolder(connect, yeomanConfig.dist)
];
}
}
}
},
FYI Yeoman/Grunt recently changed the default template for new Gruntfiles.
Copying the default middlewares logic worked for me:
middleware: function (connect, options) {
var middlewares = [];
var directory = options.directory || options.base[options.base.length - 1];
// enable Angular's HTML5 mode
middlewares.push(modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']));
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
options.base.forEach(function(base) {
// Serve static files.
middlewares.push(connect.static(base));
});
// Make directory browse-able.
middlewares.push(connect.directory(directory));
return middlewares;
}
UPDATE: As of grunt-contrib-connect 0.9.0, injecting middlewares into the connect server is much easier:
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
grunt.initConfig({
// The actual grunt server settings
connect: {
livereload: {
options: {
/* Support `$locationProvider.html5Mode(true);`
* Requires grunt 0.9.0 or higher
* Otherwise you will see this error:
* Running "connect:livereload" (connect) task
* Warning: Cannot call method 'push' of undefined Use --force to continue.
*/
middleware: function(connect, options, middlewares) {
var modRewrite = require('connect-modrewrite');
// enable Angular's HTML5 mode
middlewares.unshift(modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']));
return middlewares;
}
}
}
}
});
}
There is a pull request I sent for this problem: https://github.com/yeoman/generator-angular/pull/132, but you need to apply it manually.
To deeply simplify #Zuriel's answer, here's what I found to work on my behalf.
Install connect-modrewrite: npm install connect-modrewrite --save
Include it in your grunt file: var rewrite = require( "connect-modrewrite" );
Modify your connect options to use the rewrite:
connect: {
options: {
middleware: function ( connect, options, middlewares ) {
var rules = [
"!\\.html|\\.js|\\.css|\\.svg|\\.jp(e?)g|\\.png|\\.gif$ /index.html"
];
middlewares.unshift( rewrite( rules ) );
return middlewares;
}
},
server: {
options: {
port: 9000,
base: "path/to/base"
}
}
}
Simplified this as much as possible. Because you have access to the middlewares provided by connect, it's easy to set the rewrite to the first priority response. I know it's been a while since the question has been asked, but this is one of the top results of google searching regarding the problem.
Idea came from source code: https://github.com/gruntjs/grunt-contrib-connect/blob/master/Gruntfile.js#L126-L139
Rules string from: http://danburzo.ro/grunt/chapters/server/
I tried all of these, but had no luck. I am writing an angular2 app, and the solution came from grunt-connect pushstate.
All I did was:
npm install grunt-connect-pushstate --save
and in the grunt file:
var pushState = require('grunt-connect-pushstate/lib/utils').pushState;
middleware: function (connect, options) {
return [
// Rewrite requests to root so they may be handled by router
pushState(),
// Serve static files
connect.static(options.base)
];
}
and it all worked like magic.
https://www.npmjs.com/package/grunt-connect-pushstate

Resources