Tôi đang sử dụng Grunt và thi hành cmd "grunt build" để tạo thư mục phân phối chứa ứng dụng AngularJS.Xây dựng Grunt khiến ứng dụng Angular gặp sự cố trên
Là ứng dụng độc lập của tôi hoạt động tốt. Khi tôi tạo bản phân phối cho ứng dụng, ứng dụng sẽ bắt đầu gặp sự cố khá nhanh.
tôi nhìn thấy trong Công cụ F12 Console là:
10 $ digest() lặp đạt được. Hủy bỏ!
Tôi nghi ngờ một tệp trong thư mục .tmp của tôi có tên vendor.js và không thể rút gọn, làm xấu và ghép chính xác tệp này vì các biến tiêm phụ thuộc của trình điều khiển mangling đối số điều khiển được nhúng như "$ scope" tới " một ví dụ, mặc dù tôi đang sử dụng ngAnnotate.
Xem Tôi đang sử dụng UglifyJs và gọi ngAnnotate trước khi làm xấu đi và concat nhưng tôi không thể loại bỏ UglifyJs từ useMinPrepare hoặc tôi có lỗi khác như thư mục script thậm chí không được tạo ra trong thư mục TP của tôi:
useminPrepare: {
html: '<%= yeoman.app %>/index.html',
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
tôi đang thiết lập mangle = false trong tập tin GruntJs của tôi nhưng tôi nghi ngờ sử dụngMinPrepare js: ['concat', 'uglifyjs']
thay đổi trình tự thực hiện và chạy uglify trước khi ẩn Chú thích có thể chạy khi useMin
được gọi, mặc dù tôi gọi useMin
sau ngAnnotate
.
Tôi mới sử dụng Grunt và ứng dụng này đã được chuyển cho tôi từ một nhà phát triển khác.
tôi tìm thấy bài viết này sẽ không chính xác có ý nghĩa với tôi và cũng không phải là một sự thay đổi mã mà dường như áp dụng đối với Gruntfile.js của tôi, nhưng tôi nghĩ có lẽ tôi đã vào một cái gì đó:
https://github.com/DaftMonk/generator-angular-fullstack/issues/164
Tôi đã đặt tùy chọn xoài Uglify thành false nhưng không khắc phục được sự cố của tôi.
Đây là mã Gruntfile.js tôi:
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
grunt.loadNpmTasks('grunt-connect-proxy');
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
yeoman: {
// configurable paths
app: require('./bower.json').appPath || 'app',
dist: 'dist'
},
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['bowerInstall']
},
js: {
files: ['<%= yeoman.app %>/scripts/**/*.js'],
// tasks: ['newer:jshint:all'],
options: {
livereload: true
}
},
html: {
files: ['**/*.html'],
options: {
livereload: true
}
},
jsTest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['newer:jshint:test', 'karma']
},
compass: {
files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['compass:server', 'autoprefixer']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= yeoman.app %>/{,*/}*.html',
'.tmp/styles/{,*/}*.css',
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
//hostname: 'localhost',
livereload: 35729
},
proxies: [{
context: ['/api', '/images'],
host: '127.0.0.1',
port: 60878,
changeOrigin: true
}],
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= yeoman.app %>'
],
middleware: function (connect, options) {
var middlewares = [];
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
// Setup the proxy
middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest);
// setup push state
middlewares.push(require('grunt-connect-pushstate/lib/utils').pushState());
// Serve static files
options.base.forEach(function(base) {
middlewares.push(connect.static(base));
});
return middlewares;
}
}
},
test: {
options: {
port: 9001,
base: [
'.tmp',
'test',
'<%= yeoman.app %>'
]
}
},
dist: {
options: {
base: '<%= yeoman.dist %>',
middleware: function (connect, options) {
var middlewares = [];
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
// Setup the proxy
middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest);
// setup push state
middlewares.push(require('grunt-connect-pushstate/lib/utils').pushState());
// Serve static files
options.base.forEach(function(base) {
middlewares.push(connect.static(base));
});
return middlewares;
}
}
}
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: [
'Gruntfile.js',
'<%= yeoman.app %>/scripts/{,*/}*.js'
],
test: {
options: {
jshintrc: 'test/.jshintrc'
},
src: ['test/spec/{,*/}*.js']
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/*',
'!<%= yeoman.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the app
bowerInstall: {
app: {
src: ['<%= yeoman.app %>/index.html'],
ignorePath: '<%= yeoman.app %>/'
// ,exclude : ["bower_components/angular-snap/angular-snap.css"]
},
sass: {
src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
ignorePath: '<%= yeoman.app %>/bower_components/'
}
},
// Compiles Sass to CSS and generates necessary files if requested
compass: {
options: {
sassDir: '<%= yeoman.app %>/styles',
cssDir: '.tmp/styles',
generatedImagesDir: '.tmp/images/generated',
imagesDir: '<%= yeoman.app %>/images',
javascriptsDir: '<%= yeoman.app %>/scripts',
fontsDir: '<%= yeoman.app %>/styles/fonts',
importPath: '<%= yeoman.app %>/bower_components',
httpImagesPath: '/images',
httpGeneratedImagesPath: '/images/generated',
httpFontsPath: '/styles/fonts',
relativeAssets: false,
assetCacheBuster: false,
raw: 'Sass::Script::Number.precision = 10\n'
},
dist: {
options: {
generatedImagesDir: '<%= yeoman.dist %>/images/generated',
fontsDir: '<%= yeoman.dist %>/styles/fonts'
}
},
server: {
options: {
debugInfo: false
}
}
},
// Renames files for browser caching purposes
rev: {
dist: {
files: {
src: [
'<%= yeoman.dist %>/scripts/{,*/}*.js',
'<%= yeoman.dist %>/styles/{,*/}*.css',
'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
// ,'<%= yeoman.dist %>/styles/fonts/*'
]
}
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
html: '<%= yeoman.app %>/index.html',
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
uglify: {
dist: {
options : {
report: 'min',
mangle : false
// compress: false,
// beautify : true
}
}
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
options: {
assetsDirs: ['<%= yeoman.dist %>', '<%= yeoman.dist %>/styles/fonts', '<%= yeoman.dist %>/images' ]
}
},
concat: {
options: {
separator: grunt.util.linefeed + ";" + grunt.util.linefeed
}
},
// The following *-min tasks produce minified files in the dist folder
// cssmin: {
// options: {
// root: '<%= yeoman.dist %>'
// }
// },
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true,
removeOptionalTags: true
},
files: [{
expand: true,
cwd: '<%= yeoman.dist %>',
src: ['*.html', 'scripts/{,*/}*.html'],
dest: '<%= yeoman.dist %>'
}]
}
},
// ngmin tries to make the code safe for minification automatically by
// using the Angular long form for dependency injection. It doesn't work on
// things like resolve or inject so those have to be done manually.
ngAnnotate: {
dist: {
files: [{
expand: true,
cwd: '.tmp/concat/scripts',
src: '*.js',
dest: '.tmp/concat/scripts'
}]
}
},
ngtemplates: {
fctrs: {
cwd: "<%= yeoman.app %>",
src: ['scripts/**/*.html'],
dest: '.tmp/concat/scripts/templates.js'
}
},
// Replace Google CDN references
cdnify: {
dist: {
html: ['<%= yeoman.dist %>/*.html']
}
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,*/}*.html',
'images/{,*/}*.{webp}',
'styles/fonts/*',
'statics/**',
'test_data/**/*.json'
]
},
{
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: ['generated/*']
}]
},
styles: {
expand: true,
cwd: '<%= yeoman.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
processhtml: {
options : {
commentMarker : "process"
},
dist: {
files: {
'<%= yeoman.dist %>/index.html':['<%= yeoman.dist %>/index.html']
}
}
},
// Run some tasks in parallel to speed up the build process
concurrent: {
server: [
'compass:server'
],
test: [
'compass'
],
dist: [
'compass:dist',
'imagemin',
'svgmin'
]
},
// Test settings
karma: {
unit: {
configFile: 'karma.conf.js',
singleRun: true
}
}
});
grunt.registerTask('serve', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'configureProxies:server', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'bowerInstall',
'concurrent:server',
'autoprefixer',
'configureProxies:server',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('server', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run(['serve:' + target]);
});
grunt.registerTask('test', [
'clean:server',
'concurrent:test',
'autoprefixer',
'connect:test',
'karma'
]);
grunt.registerTask('build', [
'clean:dist',
'bowerInstall',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'concat',
'ngAnnotate',
'ngtemplates',
'copy:dist',
'cdnify',
'cssmin',
'uglify',
'rev',
'usemin',
'processhtml',
'htmlmin'
]);
grunt.registerTask('default', [
'newer:jshint',
'test',
'build'
]);
};
[Góc yêu cầu khi bạn rút gọn, không "mangle"] (http://google.com/search?q=angular+mangle) – laggingreflex
Chạy 'grunt serve: dist', thao tác này sẽ quay lên máy chủ thử nghiệm từ thư mục dist để bạn có thể thấy lỗi xảy ra bên ngoài ứng dụng bạn đang di chuyển đến. – Terry
Có Tôi đang gặp lỗi tương tự với dịch vụ grunt: dist –