My bower_component are not created. I have one dev profile inside my pom.xml file and when I execute the command mvn clean install -P dev I get error Warning: Unable to read "C:\test-widgets\xcomponent-widgets\target/bower_components/angular-animate/angular-animate.js" file (Error code: ENOENT). Use --force to continue.
My dev profile looks like this
<profile>
<id>dev</id>
<properties>
<grunt.build.file>gruntfile-dev.js</grunt.build.file>
<bower.components.dir>webapp/bower_components</bower.components.dir>
</properties>
<build>
<plugins>
<!-- For development, launch the grunt serve after compile phase -->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<workingDirectory>${basedir}/target</workingDirectory>
</configuration>
<executions>
<execution>
<id>grunt-fix-ngdocs</id>
<phase>none</phase>
</execution>
<execution>
<id>grunt-build</id>
<phase>compile</phase>
<goals>
<goal>grunt</goal>
</goals>
<configuration>
<arguments>build</arguments>
</configuration>
</execution>
<execution>
<id>grunt-dist</id>
<phase>none</phase>
</execution>
<execution>
<id>grunt-serve</id>
<phase>test</phase>
<goals>
<goal>grunt</goal>
</goals>
<configuration>
<arguments>serve</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6.1</version>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>${project.build.directory}</directory>
<excludes>
<exclude>**/node/**</exclude>
<exclude>**/node_modules/**</exclude>
</excludes>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
</profile>
and my grunt file dev.js looks like this
'use strict';
// Grunt file for de only
// Removed tasks for dist
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Project settings
yeoman: {
// configurable paths
app: require('${project.build.directory}/bower.json').appPath || 'components',
sources: '${basedir}/src/main/webapp/components',
modules: '${basedir}/src/main/webapp/modules',
sourcesSass: '${basedir}/src/main/webapp/components',
testSources: '${basedir}/src/test',
resourcesDocs: '${basedir}/src/main/resources/docs',
base: '${basedir}',
// Target folder where all generated files are placed
target: '${project.build.directory}',
// Distribution folder is defined on target\dist
dist: '${project.build.directory}/dist',
// Minimal distribution folder is defined on target\binDist
binDist: '${project.build.directory}/binDist',
// Distribution folder for vendor assets
vendor: '${project.build.directory}/dist/vendor',
// Documentation folder is defined on target\docs
docs: '${project.build.directory}/docs',
tmp: '${project.build.directory}/.tmp',
bower: '${project.build.directory}/bower_components'
},
watch: {
docJS: {
files: ['<%= yeoman.sources %>/**/*.*'],
tasks: ['jsdocs'],
options: {
livereload: true,
}
},
docSCSS: {
files: ['<%= yeoman.sources %>/**/*.scss'],
tasks: ['compass', 'jsdocs'],
options: {
livereload: true,
}
}
},
// Empties folders to start fresh
clean: {
options: {
force: true
},
// Clean target index html
targetIndexHtml: {
files: [
{
src: '<%= yeoman.target %>/index.html'
}
]
},
// Clean target template cache
targetTemplateCache: {
files: [
{
src: '<%= yeoman.target %>/<%= pkg.name %>-template-cache.js'
}
]
},
// Clean build folder .tmp
targetTemp: {
files: [
{
dot: true,
src: '<%= yeoman.target %>/.tmp'
}
]
},
// Clean build folder components
targetComponents: {
files: [
{
dot: true,
src: '<%= yeoman.target %>/components'
}
]
},
// Clean build folder css
targetCSS: {
files: [
{
dot: true,
src: '<%= yeoman.target %>/css'
}
]
},
// Clean distribution folder
dist: {
files: [
{
dot: true,
src: '<%= yeoman.dist %>'
}
]
},
// Clean minimal distribution folder
binDist: {
files: [
{
dot: true,
src: '<%= yeoman.binDist %>'
}
]
},
// Clean documentation folder
docs: {
files: [
{
dot: true,
src: '<%= yeoman.docs %>'
},
{
dot: true,
src: '<%= yeoman.tmp %>/doc'
}
]
}
},
// Copies files to places other tasks can use
copy: {
// Copy sources javascript to build directory
targetJS: {
files: [
{
expand: true,
dot: true,
cwd: '<%= yeoman.sources %>',
dest: '<%= yeoman.target %>/components',
src: [
'**/*.js',
'*/*'
]
}
]
},
// Copy index html page to build directory
targetIndexHtml: {
files: [
{
src: '${basedir}/src/main/webapp/index.html',
dest: '<%= yeoman.target %>/index.html'
}
]
},
docsFont: {
files: [
{
expand: true,
cwd: '<%= yeoman.bower %>/font-awesome/fonts/',
dest: '<%= yeoman.docs %>/fonts/',
src: ['**/*.*']
},
{
expand: true,
cwd: '<%= yeoman.sources %>/vendor/black-tie/fonts/',
dest: '<%= yeoman.docs %>/fonts/',
src: ['**/*.*']
},
{
expand: true,
cwd: '<%= yeoman.bower %>/bootstrap/fonts/',
dest: '<%= yeoman.docs %>/fonts/',
src: ['**/*.*']
}
]
},
docsBootstrap: {
files: [
{
expand: true,
cwd: 'bower_components/bootstrap/dist/css/',
dest: '<%= yeoman.docs %>/css/',
src: ['*.map']
}
]
},
docsResource: {
files: [
{
expand: true,
dot: true,
cwd: '<%= yeoman.resourcesDocs %>',
dest: '<%= yeoman.docs %>/doc_resource/',
src: ['**/*.pdf', '**/*.json']
}
]
},
docsTimeline: {
files: [
{
expand: true,
cwd: '<%= yeoman.sources %>/vendor/TimelineJS/build',
dest: '<%= yeoman.docs %>',
src: ['css/**/*.*']
}
]
},
docsPdf: {
files: [
{
expand: true,
dot: true,
cwd: '<%= yeoman.target %>/xcomponent-customization/pdfViewer',
dest: '<%= yeoman.docs %>/pdfViewer/',
src: ['**']
}
]
},
ngDocsPatch: {
// T2i fix for ng-docs issue that routing does not work in AngularjS 1.6
files: [
{
expand: true,
dot: true,
cwd: '<%= yeoman.resourcesDocs %>',
dest: '${project.build.directory}/node_modules/grunt-ngdocs/src/templates/js',
src: ['docs.js']
}
]
}
},
// Generate javascript template cache file
ngtemplates: {
options: {
url: function (url) {
return url.split("/").pop();
},
htmlmin: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true, // Only if you don't use comment directives!
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
}
},
'xcomponent-widgets': {
cwd: '<%= yeoman.sources %>',
src: ['**/*-template.html', '**/*-tpl.html', '**/template/*.html', '**/templates/*.html'],
dest: '<%= yeoman.target %>/<%= pkg.name %>-template-cache.js'
},
// module enhancement
't2i-common': {
cwd: '<%= yeoman.sources %>',
src: ['**/dialog-box.html', '**/t2i-spinner.html', '**/search-field.html', '**/version-display.html', '**/t2i-badge.html'],
dest: '<%= yeoman.target %>/templates/t2i-common-template-cache.js'
},
'pdf-viewer': {
cwd: '<%= yeoman.sources %>/pdf-viewer',
src: ['**/*.html'],
dest: '<%= yeoman.target %>/templates/pdf-viewer-template-cache.js'
},
'vertical-menu': {
cwd: '<%= yeoman.sources %>/vertical-menu',
src: ['**/*.html'],
dest: '<%= yeoman.target %>/templates/vertical-menu-template-cache.js'
},
'object-display-list': {
cwd: '<%= yeoman.sources %>',
src: ['**/*object-display-list/*.html'],
dest: '<%= yeoman.target %>/templates/object-display-list-template-cache.js'
},
'multiple-fields-group': {
cwd: '<%= yeoman.sources %>',
src: ['**/*multiple-fields-group/*.html'],
dest: '<%= yeoman.target %>/templates/multiple-fields-group-template-cache.js'
},
'multiple-search-and-select': {
cwd: '<%= yeoman.sources %>',
src: ['**/*multiple-search-and-select/*.html'],
dest: '<%= yeoman.target %>/templates/multiple-search-and-select-template-cache.js'
},
'lookup-text-field': {
cwd: '<%= yeoman.sources %>',
src: ['**/*lookup-text-field/*.html'],
dest: '<%= yeoman.target %>/templates/lookup-text-field-template-cache.js'
},
'attach-document': {
cwd: '<%= yeoman.sources %>',
src: ['**/*attach-document/*.html'],
dest: '<%= yeoman.target %>/templates/attach-document-template-cache.js'
},
'bread-crumb': {
cwd: '<%= yeoman.sources %>',
src: ['**/bread-crumb/*.html'],
dest: '<%= yeoman.target %>/templates/bread-crumb-template-cache.js'
},
'calendar-navigation': {
cwd: '<%= yeoman.sources %>',
src: ['**/calendar-navigation/*.html'],
dest: '<%= yeoman.target %>/templates/calendar-navigation-template-cache.js'
},
'date-histogram-filter': {
cwd: '<%= yeoman.sources %>',
src: ['**/date-histogram-filter/*.html'],
dest: '<%= yeoman.target %>/templates/date-histogram-filter-template-cache.js'
},
'date-histogram-select-box-filter': {
cwd: '<%= yeoman.sources %>',
src: ['**/date-histogram-select-box-filter/*.html'],
dest: '<%= yeoman.target %>/templates/date-histogram-select-box-filter-template-cache.js'
},
'object-display-paginated-tile': {
cwd: '<%= yeoman.sources %>',
src: ['**/object-display-paginated-tile/*.html'],
dest: '<%= yeoman.target %>/templates/object-display-paginated-tile-template-cache.js'
},
'event-category-display-list': {
cwd: '<%= yeoman.sources %>',
src: ['**/event-category-display-list/**/*.html'],
dest: '<%= yeoman.target %>/templates/event-category-display-list-template-cache.js'
},
'event-tile': {
cwd: '<%= yeoman.sources %>',
src: ['**/event-tile/**/*.html'],
dest: '<%= yeoman.target %>/templates/event-tile-template-cache.js'
},
'file-manager-tile': {
cwd: '<%= yeoman.sources %>',
src: ['**/file-manager-tile/*.html'],
dest: '<%= yeoman.target %>/templates/file-manager-tile-template-cache.js'
},
'filter-sidebar': {
cwd: '<%= yeoman.sources %>',
src: ['**/filter-sidebar/*.html'],
dest: '<%= yeoman.target %>/templates/filter-sidebar-template-cache.js'
},
'flexicard-calendar': {
cwd: '<%= yeoman.sources %>',
src: ['**/flexicard-calendar/*.html'],
dest: '<%= yeoman.target %>/templates/flexicard-calendar-template-cache.js'
},
'vertical-floating-toolbar': {
cwd: '<%= yeoman.sources %>',
src: ['**/vertical-floating-toolbar/*.html','**/floating-circle-button/*.html'],
dest: '<%= yeoman.target %>/templates/vertical-floating-toolbar-template-cache.js'
},
'form-paging': {
cwd: '<%= yeoman.sources %>',
src: ['**/form-paging/*.html'],
dest: '<%= yeoman.target %>/templates/form-paging-template-cache.js'
},
'theme-dropdown-button': {
cwd: '<%= yeoman.sources %>',
src: ['**/theme-dropdown-button/*.html'],
dest: '<%= yeoman.target %>/templates/theme-dropdown-button-template-cache.js'
},
'toolbar': {
cwd: '<%= yeoman.sources %>',
src: ['**/toolbar/*.html'],
dest: '<%= yeoman.target %>/templates/toolbar-template-cache.js'
},
'workflow-display': {
cwd: '<%= yeoman.sources %>',
src: ['**/workflow-display/*.html'],
dest: '<%= yeoman.target %>/templates/workflow-display-template-cache.js'
},
'year-navigator-with-legend': {
cwd: '<%= yeoman.sources %>',
src: ['**/year-navigator-with-legend/*.html'],
dest: '<%= yeoman.target %>/templates/year-navigator-with-legend-template-cache.js'
},
'variable-list-edit': {
cwd: '<%= yeoman.sources %>',
src: ['**/variable-list-edit/*.html'],
dest: '<%= yeoman.target %>/templates/variable-list-edit-template-cache.js'
},
},
// Create javaScript docs
ngdocs: {
options: {
dest: '<%= yeoman.docs %>',
editExample: false,
scripts: [
'https://code.jquery.com/jquery-1.11.2.min.js',
'https://code.jquery.com/jquery-migrate-1.2.1.min.js',
'<%= yeoman.target %>/.tmp/concat/vendor/<%= pkg.name %>-vendor.js',
'<%= yeoman.target %>/bower_components/angular-animate/angular-animate.js',
'<%= yeoman.target %>/bower_components/iscroll/build/iscroll-probe.js',
'<%= yeoman.target %>/bower_components/ng-file-upload/ng-file-upload.js',
'<%= yeoman.target %>/<%= pkg.name %>.js',
'<%= yeoman.sources %>/vendor/TimelineJS/build/js/storyjs-embed.js',
'<%= yeoman.resourcesDocs %>/documentation_override.js',
'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false'
],
styles: [
'<%= yeoman.target %>/.tmp/concat/vendor/<%= pkg.name %>-vendor.css',
'<%= yeoman.target %>/<%= pkg.name %>.css',
'<%= yeoman.sources %>/vendor/TimelineJS/build/css/timeline.css',
'<%= yeoman.resourcesDocs %>/documentation_override.css'
],
html5Mode: false,
startPage: '/api',
title: "xcomponent-widget-js",
bestMatch: true
},
api: {
src: ['<%= yeoman.sources %>/**/*.js', '<%= yeoman.resourcesDocs %>/api/*.ngdoc'],
title: 'API Documentation'
}
},
ngAnnotate: {
dist: {
files: [
{
expand: true,
src: [
'<%= yeoman.target %>/xcomponent-widgets-js-template-cache.js',
'<%= yeoman.target %>/components/**/*.js',
'<%= yeoman.target %>/scripts/**/*.js'
]
}
]
}
},
useminPrepare: {
html: ['<%= yeoman.target %>/index.html'],
options: {
dest: '<%= yeoman.target %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['concat', 'cssmin'],
copy: ['concat']
},
post: {}
}
}
}
},
usemin: {
html: ['<%= yeoman.target %>/{,*/}*.html'],
css: ['<%= yeoman.target %>/styles/{,*/}*.css'],
options: {
dirs: ['<%= yeoman.target %>'],
assetsDirs: [
'<%= yeoman.target %>',
'<%= yeoman.target %>/images',
'<%= yeoman.target %>/styles']
}
},
// Compiles Sass to CSS and generates necessary files if requested
compass: {
dist: {
options: {
sassDir: '<%= yeoman.sources %>/',
cssDir: '<%= yeoman.target %>/css',
relativeAssets: true,
assetCacheBuster: false,
generatedImagesDir: '<%= yeoman.target %>/images',
httpPath: ".",
httpImagesPath: '/images',
httpGeneratedImagesPath: '/images',
httpFontsPath: '/fonts',
raw: 'Sass::Script::Number.precision = 10\n'
}
}
},
// Minify css files
cssmin: {
// Concat and minify all css on the distribution folder
dist: {
files: {
'<%= yeoman.target %>/<%= pkg.name %>.min.css': [
'<%= yeoman.target %>/css/**/*.css'
]
}
}
},
// Minify js files
uglify: {
options: {
mangle: false
},
dist: {
files: {
'<%= yeoman.target %>/<%= pkg.name %>.min.js': [
'<%= yeoman.target %>/<%= pkg.name %>.js'
]
}
},
distTemplate: {
files: {
'<%= yeoman.target %>/dist/scripts/<%= pkg.name %>-template.min.js': [
'<%= yeoman.target %>/.tmp/concat/scripts/<%= pkg.name %>-template.js'
]
}
},
distCore: {
files: {
'<%= yeoman.target %>/dist/scripts/<%= pkg.name %>-core.min.js': [
'<%= yeoman.target %>/.tmp/concat/scripts/<%= pkg.name %>-core.js'
]
}
},
distOrganigram: {
files: {
'<%= yeoman.target %>/dist/scripts/<%= pkg.name %>-organigram.min.js': [
'<%= yeoman.target %>/.tmp/concat/scripts/<%= pkg.name %>-organigram.js'
]
}
},
distParameterValue: {
files: {
'<%= yeoman.target %>/dist/scripts/<%= pkg.name %>-parameter-value.min.js': [
'<%= yeoman.target %>/.tmp/concat/scripts/<%= pkg.name %>-parameter-value.js'
]
}
},
distTimeline: {
files: {
'<%= yeoman.target %>/dist/scripts/<%= pkg.name %>-timeline.min.js': [
'<%= yeoman.target %>/.tmp/concat/scripts/<%= pkg.name %>-timeline.js'
]
}
},
distFile: {
files: {
'<%= yeoman.target %>/dist/scripts/<%= pkg.name %>-file.min.js': [
'<%= yeoman.target %>/.tmp/concat/scripts/<%= pkg.name %>-file.js'
]
}
},
},
concat: {
// Concat all sources
jsTargetAll: {
src: [
// begin t2i modules in xcomponent-widgets
'<%= yeoman.modules %>/*.js',
// end t2i modules in xcomponent-widgets
'<%= yeoman.sources %>/**/*.js',
'<%= yeoman.target %>/xcomponent-customization/angular-strap/angular-strap.js',
'<%= yeoman.target %>/xcomponent-customization/angular-strap/angular-strap.tpl.js',
'!<%= yeoman.sources %>/vendor/TimelineJS/build/js/storyjs-embed.js',
'<%= yeoman.target %>/<%= pkg.name %>-template-cache.js',
// begin t2i modules in xcomponent-widgets
'<%= yeoman.target %>/templates/*.js',
// end t2i modules in xcomponent-widgets
],
dest: '<%= yeoman.target %>/<%= pkg.name %>.js'
},
jsTargetNoTemplateCache: {
src: [
'<%= yeoman.sources %>/xcomponent-widgets.js',
'<%= yeoman.sources %>/**/*.js',
'!<%= yeoman.sources %>/xcomponent-widgets-tpl-cache.js'
],
dest: '<%= yeoman.target %>/<%= pkg.name %>-without-template-cache.js'
},
// Concat all css
cssDist: {
src: ['<%= yeoman.target %>/css/**/*.css'],
dest: '<%= yeoman.target %>/<%= pkg.name %>.css'
}
},
connect: {
doc: {
options: {
port: 9010,
base: '<%= yeoman.docs %>',
open: "http://localhost:9010/#/api",
hostname: '0.0.0.0',
livereload: true
}
}
}
});
grunt.registerTask('jsdocs', [
"clean:docs",
'newer:copy:targetIndexHtml',
'newer:copy:targetJS',
'ngtemplates', // Generate template cache
'newer:compass', // Compile scss to css
'useminPrepare', // Prepare usemin tasks for minification
'concat', // Concat sources for distribution
'ngAnnotate',
'usemin',
'copyDocs', // Copy resources for documentation,
'ngdocs' // Build documentation
]);
grunt.registerTask('copyDocs', [
'copy:docsResource',
'copy:docsTimeline',
'copy:docsPdf',
'copy:docsFont',
'copy:docsBootstrap',
]);
// 1. Run grunt build by frontend-maven-plugin
grunt.registerTask('build', [
'clean', // Clean folders
'copy:targetIndexHtml',
'copy:targetJS',
'ngtemplates', // Generate template cache
'compass', // Compile scss to css
'useminPrepare', // Prepare usemin tasks for minification
'concat', // Concat sources for distribution
'ngAnnotate',
'usemin'
]);
// 2. Build pdf js (npm run build-pdf-js) in frontend-maven-plugin
// 3. Run grunt dist by frontend-maven-plugin
grunt.registerTask('serve', [
'copyDocs', // Copy resources for documentation,
'ngdocs', // Build documentation
'connect:doc',
'watch'
]);
grunt.registerTask('dist', [
]);
};
where is the mistake ? I can't find out why when i execute the command the bower_components folder with the dependencies is not created
I tried to change the <bower.components.dir> from webapp/bower_components to bower_components to search
on the root but after that I get error
Warning: Unable to create directory "C:\test-widgets\xcomponent-widgets\target\components\bread-crumb"
So I have started yo angular for a new project and it's great, the only issue is that I like to structure my views and have partials etc, for example a great structure for me is something like the following:
app/views/_partials/modals
app/views/_partials/menus
app/views/_partials/buttons
app/views/index.html
app/views/about.html
However, it appears that the angular generator doesn't look in sub directories when building into the dist folder and I get all sorts of missing includes and errors.
Can I change Grunt to look into these sub directories and process the views accordingly so that they appear within my app after building?
I located an interesting block that I think could be responsible in my Grunt file:
ngtemplates: {
dist: {
options: {
module: 'myApp',
htmlmin: '<%= htmlmin.dist.options %>',
usemin: 'scripts/scripts.js'
},
cwd: '<%= yeoman.app %>',
src: 'views/{,*/}*.html',
dest: '.tmp/templateCache.js'
}
},
Or is it something in the usemin block? I'm confused (relatively new to Angular):
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']]
}
}
},
Ok, so I figured this one out, the issue was in the ngtemplates block and my code now looks like this:
ngtemplates: {
dist: {
options: {
module: 'myApp',
htmlmin: '<%= htmlmin.dist.options %>',
usemin: 'scripts/scripts.js'
},
cwd: '<%= yeoman.app %>',
src: 'views/**/**/*.html',
dest: '.tmp/templateCache.js'
}
},
Notice the src attribute has changed from:
src: 'views/{,*/}*.html',
to:
src: 'views/**/**/*.html',
This seems to capture all my templates within the _partials directories
I have an angular app that I have scaffolded using yeoman.
When I am trying to build with grunt, no views directory is generated in dist/
This is how my GruntFile looks
htmlmin: {
dist: {
options: {
collapseWhitespace: false,
conservativeCollapse: false,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true
},
files: [{
expand: true,
cwd: '<%= yeoman.dist %>',
src: ['*.html'],
dest: '<%= yeoman.dist %>'
}]
}
},
ngtemplates: {
dist: {
options: {
module: 'tweetSearchApp',
htmlmin: '<%= htmlmin.dist.options %>',
usemin: 'scripts/scripts.js'
},
cwd: '<%= yeoman.app %>',
src: 'views/{,*/}*.html',
dest: '.tmp/templateCache.js'
}
},
And this is how my grunt logs look like
Running "ngtemplates:dist" (ngtemplates) task
File .tmp/templateCache.js created.
>> Usemin has not created uglify.generated yet!
And
Running "usemin:html" (usemin) task
Replaced 2 references to assets
Running "usemin:css" (usemin) task
Replaced 2 references to assets
Running "usemin:js" (usemin) task
Replaced 2 references to assets
Running "htmlmin:dist" (htmlmin) task
Minified 2 files
But I still cannot see any views folder generated in my dist/ folder
Please help me with the configuration
Please have a look to this link
https://www.npmjs.com/package/grunt-angular-templates
Grunt is caching your HTML templates with $templateCache. That means all your Html files were included in the script*.js file which was generated in dist/scripts/script*.js.
That is why the views directory is not being generated in dist/
Make change in your gruntfile.js
htmlmin. files.src: ['.html', '{,/}*.html']and
copy.dist.files.src:[
'.{ico,png,txt}',
'.htaccess',
'.html',
'{,/}.html',
'images/{,/}.{webp}',
'styles/fonts/{,/}.*'
]
In this way it is working for me.
On my project I added to my bower.json some projects that use fonts:
fontawesome
bootstrap
roboto-fontface
Grunt file was mainly generated by "yo angular" with some custom edits. Fonts work just fine in "grunt serve" development mode but don't work when I do my dist build with "grunt".
The problem is that fonts aren't copied to my dist folder. To fix that I manually changed my Gruntfile to copy:dist all my fonts. Like this:
{
expand: true,
cwd: "<%= yeoman.app %>/bower_components/bootstrap/dist/fonts",
dest: "<%= yeoman.dist %>/fonts",
src: ["*.*"]
}
My problem now is that all my libraries CSS expect the fonts to be on a specific folder ( roboto-fontface and bootstrap for example expect the font to be in different folders).
So I'll have to change my gruntfile to replace the fonts reference on the *.css files to target the right paths. I don't know yet how to do this but my main itch is that this seems very "hacky"
Bower works very well with my css files: they are automatically added to index.html and their href is correctly replaced when doing my dist build. For example I can upgrade my ng-grid project without problems, remove and add new projects. I believe that works because of the bower.json file on the ng-grid project that contains
"main": ["./ng-grid.css", "./build/ng-grid.js"]
Grunt is correctly configured to understand that and add it to my index.html.
But for fonts it seems the only solution is to to modify my gruntfile to add copy:dist and then some kind of regex replacement on my *css files. But, for example, the roboto-fontface project bower.json file also seems to have a good "main" where all the fonts are listed besides the css file.
For me it seems logical that I should be able to configure my Gruntfile so that it understands that the "main" parameter has fonts and automatically copies them to my dist/ and replaces my css files with the correct path.
When I add a new font to my project I'll have to edit my Gruntfile, also when I remove/update fonts.
So, the question is simple: how can I best manage my project fonts? What are the best practices? How are the 'cool kids' doing it?
I ran into this issue a few weeks ago, I also used yeoman-angular-generator and had to tweak the copy:dist as well.
In my project I was using 3 separate fonts, font-awesome, lato and open-sans. I added font-awesome via bower but the other 2 I manually downloaded them and placed them under app/fonts
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,*/}*.html',
'images/{,*/}*.{png, jpg, jpeg, gif,webp}',
//any new font you drop under app/fonts will be copied to dist
'fonts/**'
]
}, {
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 %>'
}, {
expand: true,
dot: true,
cwd: 'bower_components/font-awesome',
src: ['fonts/*.*'],
dest: '<%= yeoman.dist %>'
}]
},
styles: {
expand: true,
cwd: '<%= yeoman.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
//rest of Gruntfile...
Hope this helps!
When I grunt build my AngularJS app grunt-rev has a problem dealing with the fonts. It will create the font folders just fine but does not place any fonts in them. Here is what it shows me.
Running "rev:dist" (rev) task
dist/scripts/scripts.js >> a3e641ec.scripts.js
dist/styles/main.css >> 970b8797.main.css
Warning: Unable to read "dist/fonts/Aller" file (Error code: EISDIR). Use --force to continue.
grunt-rev in my Gruntfile.js
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/*'
]
}
}
}
How to fix this?
I finally solved this problem by using the double asterisk ** method to match all the sub directories recursively. I don't know why that method was not used in my original Gruntfile.js. Instead it used the {,*/}* which did not behave recursively for some reason. So here is my new rev object in my Gruntfile.js
rev: {
dist: {
files: {
src: [
'<%= yeoman.dist %>/scripts/**/*.js',
'<%= yeoman.dist %>/styles/**/*.css',
'<%= yeoman.dist %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.dist %>/fonts/**/*.ttf'
]
}
}
},
I was having the same problem. They have a bug about it in version 0.1.0.
A workaround is to specify a file extension.
Before:
rev: {
dist: {
files: [{
expand: true,
cwd: '<%= config.dist %>/',
src: [
'images/**/*'
]
}]
}
}
After:
rev: {
dist: {
files: [{
expand: true,
cwd: '<%= config.dist %>/',
src: [
'images/**/*.{gif,jpeg,jpg,png}'
]
}]
}
}