所以我在提供构建应用程序时获得了404 error
。在开发中它没有抛出任何错误,所以我有点失去了如何解决这个问题。几天来一直在处理这个错误,我真的可以使用一些帮助。
我的问题是,为什么它仍然会调用/app/dashboard/dashboard.html
,即使它已经压缩到构建状态?
我使用 hottowel 来创建项目。我使用gulp build
来构建应用,并使用 gulp serve-build 来为应用提供服务。
浏览器控制台中的输出错误
信息中心路线
(function() {
'use strict';
angular
.module('app.dashboard')
.run(appRun);
appRun.$inject = ['routerHelper'];
/* @ngInject */
function appRun(routerHelper) {
routerHelper.configureStates(getStates());
}
function getStates() {
return [
{
state: 'dashboard',
config: {
url: '/dashboard',
templateUrl: 'app/dashboard/dashboard.html',
controller: 'DashboardController',
controllerAs: 'vm',
title: 'Admin Dashboard',
authenticated: true,
permissions: 'admin',
settings: {
nav: 2,
content: '<i class="fa fa-dashboard"></i> Dashboard'
}
}
}
];
}
})();
&#13;
gulp.js
var args = require('yargs').argv;
var browserSync = require('browser-sync');
var config = require('./gulp.config')();
var del = require('del');
var glob = require('glob');
var gulp = require('gulp');
var path = require('path');
var _ = require('lodash');
var $ = require('gulp-load-plugins')({ lazy: true });
var colors = $.util.colors;
var envenv = $.util.env;
var port = process.env.PORT || config.defaultPort;
/**
* yargs variables can be passed in to alter the behavior, when present.
* Example: gulp serve-dev
*
* --verbose : Various tasks will produce more output to the console.
* --nosync : Don't launch the browser with browser-sync when serving code.
* --debug : Launch debugger with node-inspector.
* --debug-brk: Launch debugger and break on 1st line with node-inspector.
* --startServers: Will start servers for midway tests on the test task.
*/
/**
* List the available gulp tasks
*/
gulp.task('help', $.taskListing);
gulp.task('default', ['help']);
/**
* vet the code and create coverage report
* @return {Stream}
*/
gulp.task('vet', function () {
log('Analyzing source with JSHint and JSCS');
return gulp
.src(config.alljs)
.pipe($.if(args.verbose, $.print()))
.pipe($.jshint())
.pipe($.jshint.reporter('jshint-stylish', { verbose: true }))
.pipe($.jshint.reporter('fail'))
.pipe($.jscs());
});
/**
* Create a visualizer report
*/
gulp.task('plato', function (done) {
log('Analyzing source with Plato');
log('Browse to /report/plato/index.html to see Plato results');
startPlatoVisualizer(done);
});
/**
* Compile less to css
* @return {Stream}
*/
gulp.task('styles', ['clean-styles'], function () {
log('Compiling Less --> CSS');
return gulp
.src(config.less)
.pipe($.plumber()) // exit gracefully if something fails after this
.pipe($.less())
// .on('error', errorLogger) // more verbose and dupe output. requires emit.
.pipe($.autoprefixer({ browsers: ['last 2 version', '> 5%'] }))
.pipe(gulp.dest(config.temp));
});
/**
* Copy fonts
* @return {Stream}
*/
gulp.task('fonts', ['clean-fonts'], function () {
log('Copying fonts');
return gulp
.src(config.fonts)
.pipe(gulp.dest(config.build + 'fonts'));
});
/**
* Compress images
* @return {Stream}
*/
gulp.task('images', ['clean-images'], function () {
log('Compressing and copying images');
return gulp
.src(config.images)
.pipe($.imagemin({ optimizationLevel: 4 }))
.pipe(gulp.dest(config.build + 'images'));
});
gulp.task('less-watcher', function () {
gulp.watch([config.less], ['styles']);
});
/**
* Create $templateCache from the html templates
* @return {Stream}
*/
gulp.task('templatecache', ['clean-code'], function () {
log('Creating an AngularJS $templateCache');
return gulp
.src(config.htmltemplates)
.pipe($.if(args.verbose, $.bytediff.start()))
.pipe($.minifyHtml({ empty: true }))
.pipe($.if(args.verbose, $.bytediff.stop(bytediffFormatter)))
.pipe($.angularTemplatecache(
config.templateCache.file,
config.templateCache.options
))
.pipe(gulp.dest(config.temp));
});
/**
* Wire-up the bower dependencies
* @return {Stream}
*/
gulp.task('wiredep', function () {
log('Wiring the bower dependencies into the html');
var wiredep = require('wiredep').stream;
var options = config.getWiredepDefaultOptions();
// Only include stubs if flag is enabled
var js = args.stubs ? [].concat(config.js, config.stubsjs) : config.js;
return gulp
.src(config.index)
.pipe(wiredep(options))
.pipe(inject(js, '', config.jsOrder))
.pipe(gulp.dest(config.client));
});
gulp.task('inject', ['wiredep', 'styles', 'templatecache'], function () {
log('Wire up css into the html, after files are ready');
return gulp
.src(config.index)
.pipe(inject(config.css))
.pipe(gulp.dest(config.client));
});
/**
* Run the spec runner
* @return {Stream}
*/
gulp.task('serve-specs', ['build-specs'], function (done) {
log('run the spec runner');
serve(true /* isDev */, true /* specRunner */);
done();
});
/**
* Inject all the spec files into the specs.html
* @return {Stream}
*/
gulp.task('build-specs', ['templatecache'], function (done) {
log('building the spec runner');
var wiredep = require('wiredep').stream;
var templateCache = config.temp + config.templateCache.file;
var options = config.getWiredepDefaultOptions();
var specs = config.specs;
if (args.startServers) {
specs = [].concat(specs, config.serverIntegrationSpecs);
}
options.devDependencies = true;
return gulp
.src(config.specRunner)
.pipe(wiredep(options))
.pipe(inject(config.js, '', config.jsOrder))
.pipe(inject(config.testlibraries, 'testlibraries'))
.pipe(inject(config.specHelpers, 'spechelpers'))
.pipe(inject(specs, 'specs', ['**/*']))
.pipe(inject(templateCache, 'templates'))
.pipe(gulp.dest(config.client));
});
/**
* Build everything
* This is separate so we can run tests on
* optimize before handling image or fonts
*/
gulp.task('build', ['optimize', 'images', 'fonts'], function () {
log('Building everything');
var msg = {
title: 'gulp build',
subtitle: 'Deployed to the build folder',
message: 'Running `gulp serve-build`'
};
del(config.temp);
log(msg);
notify(msg);
});
/**
* Optimize all files, move to a build folder,
* and inject them into the new index.html
* @return {Stream}
*/
gulp.task('optimize', ['inject', 'test'], function () {
log('Optimizing the js, css, and html');
var assets = $.useref.assets({ searchPath: './' });
// Filters are named for the gulp-useref path
var cssFilter = $.filter('**/*.css');
var jsAppFilter = $.filter('**/' + config.optimized.app);
var jslibFilter = $.filter('**/' + config.optimized.lib);
var templateCache = config.temp + config.templateCache.file;
return gulp
.src(config.index)
.pipe($.plumber())
.pipe(inject(templateCache, 'templates'))
.pipe(assets) // Gather all assets from the html with useref
// Get the css
.pipe(cssFilter)
.pipe($.minifyCss())
.pipe(cssFilter.restore())
// Get the custom javascript
.pipe(jsAppFilter)
.pipe($.ngAnnotate({ add: true }))
.pipe($.uglify())
.pipe(getHeader())
.pipe(jsAppFilter.restore())
// Get the vendor javascript
.pipe(jslibFilter)
.pipe($.uglify()) // another option is to override wiredep to use min files
.pipe(jslibFilter.restore())
// Take inventory of the file names for future rev numbers
.pipe($.rev())
// Apply the concat and file replacement with useref
.pipe(assets.restore())
.pipe($.useref())
// Replace the file names in the html with rev numbers
.pipe($.revReplace())
.pipe(gulp.dest(config.build));
});
/**
* Remove all files from the build, temp, and reports folders
* @param {Function} done - callback when complete
*/
gulp.task('clean', function (done) {
var delconfig = [].concat(config.build, config.temp, config.report);
log('Cleaning: ' + $.util.colors.blue(delconfig));
del(delconfig, done);
});
/**
* Remove all fonts from the build folder
* @param {Function} done - callback when complete
*/
gulp.task('clean-fonts', function (done) {
clean(config.build + 'fonts/**/*.*', done);
});
/**
* Remove all images from the build folder
* @param {Function} done - callback when complete
*/
gulp.task('clean-images', function (done) {
clean(config.build + 'images/**/*.*', done);
});
/**
* Remove all styles from the build and temp folders
* @param {Function} done - callback when complete
*/
gulp.task('clean-styles', function (done) {
var files = [].concat(
config.temp + '**/*.css',
config.build + 'styles/**/*.css'
);
clean(files, done);
});
/**
* Remove all js and html from the build and temp folders
* @param {Function} done - callback when complete
*/
gulp.task('clean-code', function (done) {
var files = [].concat(
config.temp + '**/*.js',
config.build + 'js/**/*.js',
config.build + '**/*.html'
);
clean(files, done);
});
/**
* Run specs once and exit
* To start servers and run midway specs as well:
* gulp test --startServers
* @return {Stream}
*/
gulp.task('test', ['vet', 'templatecache'], function (done) {
startTests(true /*singleRun*/, done);
});
/**
* Run specs and wait.
* Watch for file changes and re-run tests on each change
* To start servers and run midway specs as well:
* gulp autotest --startServers
*/
gulp.task('autotest', function (done) {
startTests(false /*singleRun*/, done);
});
/**
* serve the dev environment
* --debug-brk or --debug
* --nosync
*/
gulp.task('serve-dev', ['inject'], function () {
serve(true /*isDev*/);
});
/**
* serve the build environment
* --debug-brk or --debug
* --nosync
*/
gulp.task('serve-build', ['build'], function () {
serve(false /*isDev*/);
});
/**
* Bump the version
* --type=pre will bump the prerelease version *.*.*-x
* --type=patch or no flag will bump the patch version *.*.x
* --type=minor will bump the minor version *.x.*
* --type=major will bump the major version x.*.*
* --version=1.2.3 will bump to a specific version and ignore other flags
*/
gulp.task('bump', function () {
var msg = 'Bumping versions';
var type = args.type;
var version = args.ver;
var options = {};
if (version) {
options.version = version;
msg += ' to ' + version;
} else {
options.type = type;
msg += ' for a ' + type;
}
log(msg);
return gulp
.src(config.packages)
.pipe($.print())
.pipe($.bump(options))
.pipe(gulp.dest(config.root));
});
/**
* Optimize the code and re-load browserSync
*/
gulp.task('browserSyncReload', ['optimize'], browserSync.reload);
////////////////
/**
* When files change, log it
* @param {Object} event - event that fired
*/
function changeEvent(event) {
var srcPattern = new RegExp('/.*(?=/' + config.source + ')/');
log('File ' + event.path.replace(srcPattern, '') + ' ' + event.type);
}
/**
* Delete all files in a given path
* @param {Array} path - array of paths to delete
* @param {Function} done - callback when complete
*/
function clean(path, done) {
log('Cleaning: ' + $.util.colors.blue(path));
del(path, done);
}
/**
* Inject files in a sorted sequence at a specified inject label
* @param {Array} src glob pattern for source files
* @param {String} label The label name
* @param {Array} order glob pattern for sort order of the files
* @returns {Stream} The stream
*/
function inject(src, label, order) {
var options = { read: false };
if (label) {
options.name = 'inject:' + label;
}
return $.inject(orderSrc(src, order), options);
}
/**
* Order a stream
* @param {Stream} src The gulp.src stream
* @param {Array} order Glob array pattern
* @returns {Stream} The ordered stream
*/
function orderSrc(src, order) {
//order = order || ['**/*'];
return gulp
.src(src)
.pipe($.if(order, $.order(order)));
}
/**
* serve the code
* --debug-brk or --debug
* --nosync
* @param {Boolean} isDev - dev or build mode
* @param {Boolean} specRunner - server spec runner html
*/
function serve(isDev, specRunner) {
var debugMode = '--debug';
var nodeOptions = getNodeOptions(isDev);
nodeOptions.nodeArgs = [debugMode + '=5858'];
if (args.verbose) {
console.log(nodeOptions);
}
return $.nodemon(nodeOptions)
.on('restart', ['vet'], function (ev) {
log('*** nodemon restarted');
log('files changed:\n' + ev);
setTimeout(function () {
browserSync.notify('reloading now ...');
browserSync.reload({ stream: false });
}, config.browserReloadDelay);
})
.on('start', function () {
log('*** nodemon started');
startBrowserSync(isDev, specRunner);
})
.on('crash', function () {
log('*** nodemon crashed: script crashed for some reason');
})
.on('exit', function () {
log('*** nodemon exited cleanly');
});
}
function getNodeOptions(isDev) {
return {
script: config.nodeServer,
delayTime: 1,
env: {
'PORT': port,
'NODE_ENV': isDev ? 'dev' : 'build'
},
watch: [config.server]
};
}
//function runNodeInspector() {
// log('Running node-inspector.');
// log('Browse to http://localhost:8080/debug?port=5858');
// var exec = require('child_process').exec;
// exec('node-inspector');
//}
/**
* Start BrowserSync
* --nosync will avoid browserSync
*/
function startBrowserSync(isDev, specRunner) {
if (args.nosync || browserSync.active) {
return;
}
log('Starting BrowserSync on port ' + port);
// If build: watches the files, builds, and restarts browser-sync.
// If dev: watches less, compiles it to css, browser-sync handles reload
if (isDev) {
gulp.watch([config.less], ['styles'])
.on('change', changeEvent);
} else {
gulp.watch([config.less, config.js, config.html], ['browserSyncReload'])
.on('change', changeEvent);
}
var options = {
proxy: 'localhost:' + port,
port: 3000,
files: isDev ? [
config.client + '**/*.*',
'!' + config.less,
config.temp + '**/*.css'
] : [],
ghostMode: { // these are the defaults t,f,t,t
clicks: true,
location: false,
forms: true,
scroll: true
},
injectChanges: true,
logFileChanges: true,
logLevel: 'info',
logPrefix: 'hottowel',
notify: true,
reloadDelay: 0 //1000
};
if (specRunner) {
options.startPath = config.specRunnerFile;
}
browserSync(options);
}
/**
* Start Plato inspector and visualizer
*/
function startPlatoVisualizer(done) {
log('Running Plato');
var files = glob.sync(config.plato.js);
var excludeFiles = /.*\.spec\.js/;
var plato = require('plato');
var options = {
title: 'Plato Inspections Report',
exclude: excludeFiles
};
var outputDir = config.report + '/plato';
plato.inspect(files, outputDir, options, platoCompleted);
function platoCompleted(report) {
var overview = plato.getOverviewReport(report);
if (args.verbose) {
log(overview.summary);
}
if (done) { done(); }
}
}
/**
* Start the tests using karma.
* @param {boolean} singleRun - True means run once and end (CI), or keep running (dev)
* @param {Function} done - Callback to fire when karma is done
* @return {undefined}
*/
function startTests(singleRun, done) {
var child;
var excludeFiles = [];
var fork = require('child_process').fork;
var Karma = require('karma').Server;
var serverSpecs = config.serverIntegrationSpecs;
if (args.startServers) {
log('Starting servers');
var savedEnv = process.env;
savedEnv.NODE_ENV = 'dev';
savedEnv.PORT = 8888;
child = fork(config.nodeServer);
} else {
if (serverSpecs && serverSpecs.length) {
excludeFiles = serverSpecs;
}
}
new Karma({
configFile: __dirname + '/karma.conf.js',
exclude: excludeFiles,
singleRun: !!singleRun
}, function () {
done();
}).start();
////////////////
// function karmaCompleted(karmaResult) {
// log('Karma completed');
// if (child) {
// log('shutting down the child process');
// child.kill();
// }
// if (karmaResult === 1) {
// done('karma: tests failed with code ' + karmaResult);
// } else {
// done();
// }
// }
}
/**
* Formatter for bytediff to display the size changes after processing
* @param {Object} data - byte data
* @return {String} Difference in bytes, formatted
*/
function bytediffFormatter(data) {
var difference = (data.savings > 0) ? ' smaller.' : ' larger.';
return data.fileName + ' went from ' +
(data.startSize / 1000).toFixed(2) + ' kB to ' +
(data.endSize / 1000).toFixed(2) + ' kB and is ' +
formatPercent(1 - data.percent, 2) + '%' + difference;
}
/**
* Log an error message and emit the end of a task
*/
//function errorLogger(error) {
// log('*** Start of Error ***');
// log(error);
// log('*** End of Error ***');
// this.emit('end');
//}
/**
* Format a number as a percentage
* @param {Number} num Number to format as a percent
* @param {Number} precision Precision of the decimal
* @return {String} Formatted perentage
*/
function formatPercent(num, precision) {
return (num * 100).toFixed(precision);
}
/**
* Format and return the header for files
* @return {String} Formatted file header
*/
function getHeader() {
var pkg = require('./package.json');
var template = ['/**',
' * <%= pkg.name %> - <%= pkg.description %>',
' * @authors <%= pkg.authors %>',
' * @version v<%= pkg.version %>',
' * @link <%= pkg.homepage %>',
' * @license <%= pkg.license %>',
' */',
''
].join('\n');
return $.header(template, {
pkg: pkg
});
}
/**
* Log a message or series of messages using chalk's blue color.
* Can pass in a string, object or array.
*/
function log(msg) {
if (typeof (msg) === 'object') {
for (var item in msg) {
if (msg.hasOwnProperty(item)) {
$.util.log($.util.colors.blue(msg[item]));
}
}
} else {
$.util.log($.util.colors.blue(msg));
}
}
/**
* Show OS level notification using node-notifier
*/
function notify(options) {
var notifier = require('node-notifier');
var notifyOptions = {
sound: 'Bottle',
contentImage: path.join(__dirname, 'gulp.png'),
icon: path.join(__dirname, 'gulp.png')
};
_.assign(notifyOptions, options);
notifier.notify(notifyOptions);
}
module.exports = gulp;
&#13;
app.js
/*jshint node:true*/
'use strict';
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var bodyParser = require('body-parser');
var favicon = require('serve-favicon');
var logger = require('morgan');
var mongoose = require('mongoose');
var port = process.env.PORT || 8001;
var four0four = require('./utils/404')();
var multer = require('multer');
var cors = require('cors');
var route = require('./routes')(io);
var environment = process.env.NODE_ENV;
app.use(cors({ origin: '*' }));
app.use(favicon(__dirname + '/favicon.ico'));
app.use(bodyParser.json({ limit: '2mb' }));
app.use(bodyParser.urlencoded({
limit: '2mb',
extended: true,
parameterLimit: 50000
}));
app.use(logger('dev'));
app.use('/api', route);
mongoose.connect(
'mongodb://localhost/hrisdb',
{ useMongoClient: true },
function (err) {
if (err) {
console.log('Not connected to Remote Database' + err);
} else {
console.log('Successfully connected Remote Database');
}
});
console.log('connection', mongoose.connection.readyState);
console.log('About to crank up node');
console.log('PORT=' + port);
console.log('NODE_ENV=' + environment);
switch (environment) {
case 'build':
console.log('** BUILD **');
app.use(express.static('./build/'));
// Any invalid calls for templateUrls are under app/* and should return 404
app.use('/app/*', function (req, res, next) {
four0four.send404(req, res);
});
// Any deep link calls should return index.html
app.use('/*', express.static('./build/index.html'));
break;
default:
console.log('** DEV **');
app.use(express.static('./src/client/'));
app.use(express.static('./'));
app.use(express.static('./tmp'));
// Any invalid calls for templateUrls are under app/* and should return 404
app.use('/app/*', function (req, res, next) {
four0four.send404(req, res);
});
// Any deep link calls should return index.html
app.use('/*', express.static('./src/client/index.html'));
break;
}
io.on('connection', function (socket) {
console.log('connected:', socket.client.id);
socket.on('serverEventAttendance', function (data) {
console.log('this data', data);
io.emit('socketAttendanceIn', data);
});
socket.on('serverEventAttendanceOut', function (data) {
console.log('this data', data);
io.emit('socketAttendanceIn', data);
});
});
http.listen(port, function () {
console.log('Express server listening on port ' + port);
console.log('env = ' + app.get('env') +
'\n__dirname = ' + __dirname + '\nprocess.cwd = ' + process.cwd());
});
&#13;