我有一个使用yeoman,grunt和bower的AngularJS项目。一切正常。我已经使用bower添加了angularjs-datepicker
组件,并且在实时开发版本中,一切正常。但是,我无法使组件的CSS包含在prod版本中。我已经尝试了很多事情,但是无法正常工作。我尝试对Gruntfile.js
和index.html
进行了几次更改,但是没有任何效果。查看.tmp目录的style文件夹,将永远不会创建vendor.css,并且永远不会将datetime选择器中的css合并到prod构建的css中。我真的很感谢您的帮助。以下是我的bower.json
{
"name": "rfplayer",
"version": "0.0.0",
"dependencies": {
"jquery": "^3.3.0",
"angular": "^1.6.8",
"angular-ui-mask": "^1.8.7",
"bootstrap-sass-official": "^3.2.0",
"angular-route": "^1.6.8",
"angular-touch": "^1.6.8",
"angularLocalStorage": "^0.3.2",
"ng-focus-if": "^1.0.7",
"angular-loading-bar": "^0.9.0",
"angular-modal-service": "^0.13.0",
"angular-file-upload": "^2.5.0",
"angular-bootstrap": "^2.5.0",
"bootstrap-sass": "^3.3.7",
"checklist-model": "^0.11.0",
"underscore": "^1.8.3",
"file-saver": "^1.3.4",
"angularjs-datepicker": "^2.1.23"
},
"devDependencies": {
"angular-mocks": "^1.6.8",
"angular-loading-bar": "^0.9.0",
"angular-bootstrap": "^2.5.0"
},
"appPath": "app",
"moduleName": "rfplayerApp",
"overrides": {
"bootstrap": {
"main": [
"less/bootstrap.less",
"dist/css/bootstrap.css",
"dist/js/bootstrap.js"
]
}
},
"authors": [
"Pascal Batzli <pascal@tpb.eti.br>",
"André Galioni <deh.galioni@gmail.com>"
],
"description": "",
"main": "",
"license": "MIT",
"homepage": "",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"resolutions": {
"angular": ">=1.5",
"angular-modal-service": "^0.13.0",
"checklist-model": "^1.0.0"
}
}
我的index.html顶部:
<!doctype html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
<title>RFBrandMusic</title>
<base href="/" />
<meta name="description" content=''>
<meta name="viewport" content="width=device-width">
<!-- build:css(.) styles/vendor.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/angular-loading-bar/build/loading-bar.css" />
<link rel="stylesheet" href="bower_components/angularjs-datepicker/dist/angular-datepicker.css" />
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.tmp) styles/main.css -->
<link rel="stylesheet" href="/styles/main.css">
<!-- endbuild -->
</head>
还有我的bower.json
/// <binding AfterBuild='cors' />
// Generated on 2016-08-06 using generator-angular 0.15.1
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
//Usado para rewrite da URL ao utilizar o pushState do HTML5
var modRewrite = require('connect-modrewrite');
module.exports = function (grunt) {
require('time-grunt')(grunt);
require('jit-grunt')(grunt, {
useminPrepare: 'grunt-usemin',
ngtemplates: 'grunt-angular-templates',
cdnify: 'grunt-google-cdn'
});
var serveStatic = require('serve-static');
var appConfig = {
app: require('./bower.json').appPath || 'app',
dev: 'dev',
dist: 'dist'
};
grunt.initConfig({
yeoman: appConfig,
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js: {
files: ['<%= yeoman.app %>/scripts/**/{,*/}*.js'],
tasks: ['newer:jshint:all', 'newer:jscs:all'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
jsTest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
},
compass: {
files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['compass:server', 'postcss:server']
},
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}'
]
}
},
connect: {
options: {
port: 90,
hostname: 'localhost',
livereload: true
},
livereload: {
options: {
middleware: function (connect) {
return [
modRewrite(['^[^\\.]*$ /index.html [L]']),
serveStatic('.tmp'),
connect().use('/bower_components', serveStatic('./bower_components')),
connect().use('/app/styles', serveStatic('./app/styles')),
serveStatic(appConfig.app)
];
}
}
},
test: {
options: {
port: 82,
middleware: function (connect) {
return [
serveStatic('.tmp'),
serveStatic('test'),
connect().use('/bower_components', serveStatic('./bower_components')),
serveStatic(appConfig.app)
];
}
}
},
dist: {
options: {
open: true,
base: '<%= yeoman.dist %>'
}
}
},
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'<%= yeoman.app %>/scripts/{,*/}*.js'
]
},
test: {
options: {
jshintrc: 'test/.jshintrc'
},
src: ['test/spec/{,*/}*.js']
}
},
jscs: {
options: {
config: '.jscsrc',
verbose: true
},
all: {
src: [
'Gruntfile.js',
'<%= yeoman.app %>/scripts/{,*/}*.js'
]
},
test: {
src: ['test/spec/{,*/}*.js']
}
},
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/{,*/}*',
'!<%= yeoman.dist %>/.git{,*/}*'
]
}]
},
dev: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dev %>/{,*/}*',
'!<%= yeoman.dev %>/.git{,*/}*'
]
}]
},
server: '.tmp'
},
postcss: {
options: {
processors: [
require('autoprefixer')({ browsers: ['last 1 version'] })
]
},
server: {
options: {
map: true
},
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
},
dev: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: './dev/styles/'
}]
}
},
wiredep: {
app: {
src: ['<%= yeoman.app %>/index.html'],
ignorePath: /\.\.\//
},
test: {
devDependencies: true,
src: '<%= karma.unit.configFile %>',
ignorePath: /\.\.\//,
fileTypes: {
js: {
block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
detect: {
js: /'(.*\.js)'/gi
},
replace: {
js: '\'{{filePath}}\','
}
}
}
},
sass: {
src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
ignorePath: /(\.\.\/){1,2}bower_components\//
}
},
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: './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'
}
},
dev: {
options: {
generatedImagesDir: '<%= yeoman.dev %>/images/generated'
}
},
server: {
options: {
sourcemap: true
}
}
},
filerev: {
dist: {
src: [
'<%= yeoman.dist %>/scripts/{,*/}*.js',
'<%= yeoman.dist %>/styles/{,*/}*.css',
'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.dist %>/styles/fonts/*'
]
},
dev: {
src: [
'<%= yeoman.dev %>/scripts/{,*/}*.js',
'<%= yeoman.dev %>/styles/{,*/}*.css',
'<%= yeoman.dev %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.dev %>/styles/fonts/*'
]
}
},
useminPrepare: {
html: '<%= yeoman.app %>/index.html',
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglify'],
css: ['cssmin']
},
post: {}
}
}
}
},
usemin: {
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
options: {
assetsDirs: [
'<%= yeoman.dist %>',
'<%= yeoman.dist %>/images',
'<%= yeoman.dist %>/styles'
],
patterns: {
js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
}
}
},
cssmin: {
dist: {
files: {
'<%= yeoman.dist %>/styles/main.css': [
'.tmp/styles/{,*/}*.css'
]
}
}
},
uglify: {
dist: {
files: {
'<%= yeoman.dist %>/scripts/scripts.js': '.tmp/concat/scripts/scripts.js',
'<%= yeoman.dist %>/scripts/vendor.js': '.tmp/concat/scripts/vendor.js'
}
},
generated:{}
},
concat: {
dist: {}
},
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dist %>/images'
}]
},
dev: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dev %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
},
dev: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dev %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true
},
files: [{
expand: true,
cwd: '<%= yeoman.dist %>',
src: '*.html',
dest: '<%= yeoman.dist %>'
}]
}
},
ngtemplates: {
dist: {
options: {
module: 'rfplayerApp',
htmlmin: '<%= htmlmin.dist.options %>',
usemin: 'scripts/scripts.js'
},
cwd: '<%= yeoman.app %>',
src: '*.html',
dest: '.tmp/templateCache.js'
}
},
ngAnnotate: {
dist: {
files: [{
expand: true,
cwd: '.tmp/concat/scripts',
src: '*.js',
dest: '.tmp/concat/scripts'
}]
}
},
cdnify: {
dist: {
html: ['<%= yeoman.dist %>/*.html']
}
},
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*',
'views/**'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: ['generated/*']
}, {
expand: true,
cwd: '.',
src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
dest: '<%= yeoman.dist %>'
}]
},
dev: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dev %>',
src: [
'*.{ico,png,txt}',
'*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*',
'views/**'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dev %>/images',
src: ['generated/*']
}, {
expand: true,
cwd: '.',
src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
dest: '<%= yeoman.dev %>'
}]
},
styles: {
expand: true,
cwd: '<%= yeoman.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
concurrent: {
server: [
'compass:server'
],
dev: [
'compass:dev',
'imagemin:dev',
'svgmin:dev'
],
test: [
'compass'
],
dist: [
'compass:dist',
'imagemin',
'svgmin'
]
},
// Test settings
karma: {
unit: {
configFile: 'test/karma.conf.js',
singleRun: true
}
}
});
grunt.registerTask('serve', [
'clean:dev',
'wiredep',
'concurrent:dev',
'postcss:dev',
'connect:livereload',
'watch'
]);
grunt.registerTask('build', [
'clean:dist',
'clean:dev',
'wiredep',
'useminPrepare',
'concurrent:dist',
'postcss',
'ngtemplates',
'concat',
'ngAnnotate',
'copy:dist',
//'cdnify',
'cssmin:dist',
'uglify',
'filerev',
'usemin',
'htmlmin'
]);
grunt.registerTask('test', [
'clean:server',
'wiredep',
'concurrent:test',
'postcss',
'connect:test',
'karma'
]);
};
和我的main.scss顶部
$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/";
// bower:scss
@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss";
@import "bootstrap-sass/assets/stylesheets/_bootstrap.scss";
// endbower
@import "includes/measures.scss";
@import "includes/settings.scss";
@import "includes/utils.scss";
我