Grunt connect serve statics files outside root - javascript

I'm having problems to configure my grunt file to add refs (css & js) to my index.html
here's my project structure:
src/
demo/
index.html
app.js
bower_components/
angular/
angular.js
index.html:
<script src="./bower_components/angular/angular.js"></script>
<script src="../app.js"></script>
gruntFile:
connect: {
demo: {
options: {
port: 9000,
hostname: 'localhost',
open: true,
base: 'src/demo'
},
livereload: {
options: {
middleware: function(connect) {
return [
connect().use(
'/bower_components',
connect.static('./bower_components')
)
];
}
}
}
}
}
I don't know why, but index.html cannot find app.js or angular.js.

Some observations:
the web root is src/demo;
so /index.html maps to src/demo/index.html;
therefore, ../app.js from within index.html doesn't make sense, because the you can't go "up" from the web root;
./bower_components/... tries to find the bower_components directory in src/demo/ because it's a relative path, it should be /bower_components/...

Related

Cannot GET / with webpack-dev-server

How come I am getting Cannot GET / in my browser? I think it is because my webpack-dev-server does not have a route to GET the bundled files.
devServer/server.js
import config from '../../webpack.config';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
import open from 'open';
// template! https://github.com/webpack/webpack-dev-server/blob/master/examples/node-api-simple/server.js
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
contentBase: '../dist/',
stats: {
colors: true
}
});
server.listen(3000, '127.0.0.1' ,err => {
if (err) {
console.log(err);
} else {
console.log('Dev Server listening on port 3000!\n');
open("http://localhost:3000");
}
});
webpack.config.js
import webpack from "webpack";
export default {
entry: [
"./app/index"
],
devtool: "inline-source-map",
output: {
path: __dirname + "/app/dist/", // Note: Physical files are only output by the production build task `npm run build`.
publicPath: "/",
filename: "bundle.js"
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
],
module: {
rules: [
{ test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'react']
}
}}
]
}
};
Project structure
On successful build a folder dist will be created inside the app folder which currently is not there.
Once the folder is created you can try by directly hitting the file path
http://localhost:3000/app/dist/yourfile
You can access your page via localhost:3000
When you access this path webpack dev server is searching for an index.html file to serve (like any other webserver). It can not find an index.html file because you have no index.html file. The index.html file is served from the static directory, which you have defined via property contentBase: '../dist/',.
but as I see you have no directory named dist and you have no index.html in this directory.
Your script is served from the public path, that is / in your config, so you have to reference this in your index.html
Solution:
Create directory dist and put an index.html file there with the following content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="/bundle.js"></script>
</body>
</html>
For more information read here:
https://webpack.github.io/docs/webpack-dev-server.html

Adding grunt-connect-proxy to generator-angular gruntfile.js

I'm trying to add grunt-connect-proxy to my gruntfile.js in a yeoman generator-angular project (generator-angular 0.15.1) but I can't seem to get it to work since the way it's written changes and I'm inexperienced in how Grunt works.
I've read many posts about this and none are particularly up-to-date, and the gruntfile changes seemingly often in how it implements livereload middleware This makes the documentation for grunt-connect-proxy to not work in my case.
The tricky part is under livereload
This is how it looks in generator-angular gruntfile:
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
proxies: [{
context: '/api',
host: 'localhost',
port: 8080,
https: false,
xforward: false
}],
livereload: {
options: {
open: true,
// --- how the code looks like before I do anything
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect().use('/app/styles', connect.static('./app/styles')),
connect.static(appConfig.app)
];
}
}
},
...
When I look at the documentation it looks like this:
livereload: {
options: {
middleware: function (connect, options) {
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
// Setup the proxy
var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];
// Serve static files.
options.base.forEach(function(base) {
middlewares.push(connect.static(base));
});
// Make directory browse-able.
var directory = options.directory || options.base[options.base.length - 1];
middlewares.push(connect.directory(directory));
return middlewares;
}
}
}
Can someone help me translate the documentation to the new way of writing the middleware part?
Thanks!!
So I got some help and this is how it was solved:
livereload: {
options: {
open: true,
middleware: function(connect) {
var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];
return middlewares.concat(
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect().use('/app/styles', connect.static('./app/styles')),
connect.static(appConfig.app)
);
}
}
}
Hope this helps someone else too.

HTML5 Mode in angularJS

Having problem while refreshing the page when HTML5 Mode is set. When navigating to /path, it works fine but when i refresh the page or directly type localhost/path it does not work.
HTML5 Mode
Configuration:
$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(true);
You should set the base in HTML-file
<html>
<head>
<base href="/">
</head>
</html>
In this mode you can use links without the # in HTML files
link
Link in Browser:
http://www.example.com/base/path
Update on the server. At this moment, i am just using gulp module to connect.
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('connect', function(){
connect.server({
root: './app',
port: 8080
})
})
To make it work, you need to override all requests to non-static resources by your index.html...
For connect using connect-modrewrite module it would be, something like this:
var connectModRewrite = require('connect-modrewrite');
connect.server({
root: './app',
port: 8080,
middleware: function (connect) {
return [
connectModRewrite([
'!\\.html|\\.js|\\.css|\\.ico|\\.png|\\.gif|\\.jpg|\\.jpeg|\\.swf.*$ /index.html [NC,L]'
]),
connect.static('./app')
];
}
});
You can use a middle-ware to solve the problem.
Do an npm install --save connect-history-api-fallback. Add the following to your gulpfile.js
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('connect', function() {
connect.server({
root: './app',
port: 8080,
livereload: true,
middleware: function(connect, opt) {
return [ historyApiFallback ];
}
});
});

exporting TypeScript modules for browserify

I've recently converted a canvas library I wrote into typescript. I've broken the code down into classes and they all attach themselves to a cnvs module, but i'm have a hard time compiling these down to one file.
Ideally I would like to have my files run through browserify, but at the moment i just want to get it working.
One file may look like
module cnvs {
export class Shape {
// stuff here
}
}
and then another would be
/// <reference path="Shape.ts" />
module cnvs {
export class Rect extends Shape {
// rectangle stuff here
}
}
Originally I was using import Shape = require('./Shape') (with some variants, like including extension and not including leading './')
In my cnvs.ts file I would to export the cnvs module, so that when it compiles I have a single file with the entire code base in, attaching to the window OR multiple files that could then be compiled with browserify into a single file.
The full code is at http://github.com/allouis/cnvs
Thanks
Checkout out typeify:
https://github.com/bodil/typeify
Please note it run on node.js.
You can simply compile the whole project using using --out out.js typescript compiler argument. This will merge all your files for you and generate an out.js.
One thing to be aware of is that the order of code in the arguments. Check out https://github.com/basarat/grunt-ts#javascript-generation-and-ordering
I use browserify & ```typescriptifier``'...
So you would do:
/// <reference path="Shape.ts" />
...
require("Shape.ts");
This is some of my gruntfile.js
module.exports = function (grunt) {
grunt.initConfig({
clean: {
dev: ['dest/**/*.*']
},
browserify: {
dev: {
src: ['src/root.ts'],
dest: 'dest/App.js',
options: {
external: ['angular'],
transform: ['typescriptifier'],
debug: true,
bundleOptions: { debug: true },
browserifyOptions: { debug: true }
}
}
},
express: {
dev: {
options: {
bases: ['src'],
port: 5000,
hostname: '0.0.0.0',
livereload: false
}
}
},
watch: {
ts: {
files: ['src/**/*.ts', '!src/**/*.d.ts'],
tasks: ['dest'],
options: {
livereload: true,
debug: false,
debounceDelay: 100
}
},
html: {
files: ['src/**/*.css', 'src/**/*.html'],
options: {
livereload: true,
debug: false,
debounceDelay: 100,
spawn: false
}
}
}
});
grunt.loadNpmTasks('grunt-express');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.registerTask('dev', ['rebuild', 'express:dev', 'watch' ]);
grunt.registerTask('build', ['browserify:dev']);
grunt.registerTask('rebuild', ['clean:dev', 'build']);
};
See
https://www.npmjs.org/package/typescriptifier

How can I use LiveReload with an AngularJS templateURL

How can I get the templateURL to reload when saved using LiveReload and Grunt?
angular.module('meshApp', [
'ngSanitize',
'ngRoute'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
});
I have a jade file views/main.jade that when I save is processed to .tmp/views/main.html, currently this works and I can see the template, however when I save LiveReload is unable reload the page.
Is there any way I can get it to work?
Also here is a link to my GruntFile incase it helps:
http://jsfiddle.net/daimz/Te5Xc/
EDIT -------------------------
When I wrote the initial answer there was not really anything really stable enough and thats why I make some adjustments to livereload. Since that time a lot changed. At this moment (early 2017) I use browser-sync & webpack, HMR.
EDIT -------------------------
I got it to work on my Angular/Ionic project.
As I assume that more people are looking for something like it I made a github repo: https://github.com/stefanKuijers/live-templates
My solution uses live.js which Martin Kool wrote (check ). I just added some code. This is how it works: You just add the path to your router in live-templates.js. The live-templates.js gets the routers routes and adds them to the live.js heartbeat.
How to use it:
- get script & save
- change the routerURL variable on line 27 to the url of your router
- include script on the page(s) where you require live reload
Let me know or and how it worked for you guys!
Cheers
I simplified my Gruntfile.js may helpful:
appPath:"", //your app path
watch: {
options: {
livereload: 35729,
debounceDelay: 500
},
gruntfile: {
files: ['Gruntfile.js']
},
css: {
//if you use less or sass,you can compile and copy here
},
js: {
files: ['<%= appPath %>/{scripts}/{,**/}*.js'],
tasks: ['newer:all']
},
html: {
files: ['<%= appPath %>/{views}/{,**/}*.html'],
tasks: ['newer:all']
},
livereload: {
options: {
livereload: 35729,
debounceDelay: 500
},
files: [
'<%= appPath %>/{,**/}*.html',
'<%= appPath %>/styles/{,**/}*.css',
'<%= appPath %>/images/{,**/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
}
and run in :
grunt.registerTask('server', [
...,
'watch'
]);
Maybe try this middleware:
var modRewrite = require('connect-modrewrite');
Then on the connect:
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
livereload: 35729
},
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= yeoman.app %>'
],
middleware: function(connect, options) {
var middlewares = [];
//Matches everything that does not contain a '.' (period)
middlewares.push(modRewrite(['^[^\\.]*$ /index.html [L]']));
options.base.forEach(function(base) {
middlewares.push(connect.static(base));
});
return middlewares;
}
}
}
You should also install modrewrite: npm install connect-modrewrite --save-dev
I am only guessing here. I hope it helps.

Categories

Resources