本文重点是详细介绍Angular.js项目的构建。gulp是优秀的自动化项目构建工具,咱们将用它完成 javascript/less/css/html/images/fonts
等文件的的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤(热重载)。bower是项目依赖管理工具。javascript
gulp运行在nodejs环境,首先安装nodejs。通常npm会随nodejs一块儿安装,npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等)。能够用node -v
查看安装的nodejs版本以及npm -v`查看npm的版本号。
安装bower:$ npm install -g bower
。css
在windows环境中,git bsah 安装bower会出现错误,能够在切换到cmd中安装
。html
$ cd d:/develop #定位到develop目录 $ mkdir angular-gulp-bower-seed #新建项目目录 $ cd angular-gulp-bower-seed #进入项目目录 $ npm init #初始化项目,并在项目项目中自动生成package.json文件 $ bower init #新建bower.json
此时项目初始化完毕,能够开始安装项目依赖java
#其余项目依赖也用此命令安装,这些依赖将自动安装到bower_component文件夹下,在代码中引入制定的位置便可 $ bower install angular jquery bootstrap --save-dev
安装时使用--save将自动保存配置信息至bower.json的dependencies数组中,使用--save-dev将自动保存配置信息至bower.json的devDependencies数组中。
保存至bower.json后,其余开发者对应下载便可(命令提示符执行bower install,则会根据bower.json下载全部依赖包,bower install --production只下载dependencies节点的包)。node
$ npm install -g gulp #全局安装gulp后能够在命令行中使用gulp命令,执行gulp任务 $ npm install --save-dev gulp $本地安装gulp插件,以便在配置文件中调用gulp插件的功能 $ npm install autoprefixer-core babel-preset-es2015 browser-sync gulp-autoprefixer gulp-babel gulp-changed gulp-clean gulp-clean-css gulp-concat gulp-csso gulp-htmlmin gulp-jshint gulp-load-plugins gulp-ng-annotate gulp-ng-html2js gulp-rename gulp-rev gulp-rev-collector gulp-sequence gulp-size gulp-uglify gulp-useref http-server jasmine-core jshint jshint-stylish url --save-dev #安装插件
项目目录结构以下:jquery
angular-gulp-bower-seed │ .bowerrc //bower安装包目录配置 │ .gitignore │ bower.json │ gulpfile.js //gulp配置文件,打包处理,开启服务等等 │ LICENSE │ mockAPI.js //构造.json数据文件后,经过读取文件方式模拟API请求,在先后端开发进度不一致时很是有用 │ package.json │ README.md │ ├─app //项目开发目录 │ │ angular.png.ico //ico图标 │ │ app.js //angular项目公共配置,包括主模块建立,路由配置,http拦截处理等 │ │ index-dist.html // 供gulp编译,引入打包后的文件(script/styles/fonts) │ │ index.html SPA项目入口 │ │ │ ├─bower_components //bower管理的依赖库 │ │ ├─angular │ │ ├─angular-bootstrap │ │ ├─angular-cookies │ │ ├─angular-local-storage │ │ ├─angular-md5 │ │ ├─angular-resource │ │ ├─angular-route │ │ ├─angular-ui │ │ ├─angular-ui-router │ │ ├─bootstrap │ │ └─jquery │ ├─data //构建json格式的静态数据(mock datas) │ │ csrfToken.json │ │ login.json │ │ │ ├─public //项目公共资源,包括字体,图片 │ │ ├─css │ │ ├─fonts │ │ └─images │ │ │ └─src //项目源代码 │ ├─controllers //控制器相关代码,语义化命名 │ │ appControllers.js │ │ │ ├─directives //自定义指令相关代码 │ │ │ directives.js //指令脚本 │ │ │ │ │ └─tpls //指令模板文件夹 │ │ datepicker.html │ │ modal.html │ │ pagination.html │ │ │ ├─filters //过滤器代码 │ │ filters.js │ │ │ ├─services //服务代码 │ │ apiServices.js //与API请求相关服务 │ │ app.util.js //公共服务 │ │ services.js //其余 │ │ │ ├─styles //项目样式文件夹 │ │ app.css │ │ directives.css │ │ page1.css │ │ page2.css │ │ │ └─templates //项目视图文件夹 │ │ app.html │ │ login.html │ │ noRight.html │ │ │ ├─modalViews //模态框视图文件夹 │ │ │ ├─page1Views //按业务划分视图1文件夹 │ │ │ └─page2Views //按业务划分视图2文件夹 │ │ ├─appDist //项目编译打包后生成目录
var gulp = require('gulp'); var gulpLoadPlugins = require('gulp-load-plugins'); var $ = plugins = gulpLoadPlugins(); var autoprefixer = require('gulp-autoprefixer'); var ngHtml2Js = require("gulp-ng-html2js"); var gulpif = require('gulp-if'); var uglify = require('gulp-uglify');//Minify JavaScript with UglifyJS2. var cleanCSS = require('gulp-clean-css'); var htmlmin = require('gulp-htmlmin'); var jshint = require('gulp-jshint'); //jshint检测javascript的语法错误 var useref = require('gulp-useref'); var csso = require('gulp-csso'); var concat = require('gulp-concat'); var rename = require("gulp-rename"); const babel = require('gulp-babel'); var browserSync = require('browser-sync'); var reload = browserSync.reload; var url = require('url'); var mockApi = require('./mockApi'); var distFolderUrl = "appDist"; gulp.task('clean', function () { return require('del')([distFolderUrl + '/**','tmp/**','dist/**']); }); gulp.task('templatesTpls', function () { return gulp.src([ './app/src/directives/tpls/*.html', ]) .pipe(ngHtml2Js({ moduleName: "myApp", prefix: "src/directives/tpls/" })) .pipe(concat("templatesTpls.min.js")) .pipe(babel({ presets: ['es2015'] })) .pipe(uglify()) .pipe(gulp.dest('./tmp/templates')) }); gulp.task('templatesViews', function () { return gulp.src([ './app/src/templates/**/*.html' ]) .pipe(ngHtml2Js({ moduleName: "myApp", rename:function (templateUrl, templateFile) { var pathParts = templateFile.path.split('\\'); var file = pathParts[pathParts.length - 1]; var folder = pathParts[pathParts.length - 2]; if ("templates" === folder) { return "./src/templates/" + file } else { return "./src/templates/" + folder + '/' + file } } })) .pipe(concat("templatesViews.min.js")) .pipe(babel({ presets: ['es2015'] })) .pipe(uglify()) .pipe(gulp.dest('./tmp/templates')) }); gulp.task('copyTemplatesToDist', function () { return gulp.src([ './app/src/templates/**/*.html', ]) .pipe(gulp.dest(distFolderUrl + '/src/templates')); }); gulp.task('copyTplsToDist', function () { return gulp.src([ './app/src/directives/tpls/**/*.html', ]) .pipe(gulp.dest(distFolderUrl + '/src/directives/tpls')); }); // gulp.task('font', function() { // return gulp.src(['./app/public/fonts/**/*'], {base: './app/'}) // .pipe(gulp.dest(distFolderUrl + '')) // }); // gulp.task('images', function() { // return gulp.src(['./app/public/images/**/*'], {base: './app/'}) // .pipe(gulp.dest(distFolderUrl + '')) // }); gulp.task('public', function() { return gulp.src(['./app/public/**/*','./app/*.ico'], {base: './app/'}) .pipe(gulp.dest(distFolderUrl)) }); gulp.task('vendorCss',function () { return gulp.src(['./app/bower_components/**/*.css']) .pipe(gulp.dest(distFolderUrl + '/vendor')) }) gulp.task('vendorFont',function () { return gulp.src([ './app/bower_components/bootstrap/dist/fonts/**']) .pipe(gulp.dest(distFolderUrl + '/vendor/bootstrap/dist/fonts')) }) gulp.task('vendorJs',function () { return gulp.src('./app/bower_components/**/*.js') .pipe(gulp.dest(distFolderUrl + '/vendor')) }) // gulp.task('vendor', ['vendorCss', 'vendorJs', 'vendorFont']); gulp.task('vendor', function () { return gulp.src(['./app/bower_components/**/*']) .pipe(gulp.dest(distFolderUrl + '/vendor')) }); var cssList = [ './app/src/styles/app.css', './app/src/styles/*.css' ]; gulp.task('css', function() { return gulp.src(cssList) .pipe(autoprefixer({ browsers: ['last 2 versions'], cascade: false })) .pipe(concat('app.min.css')) .pipe(cleanCSS()) .pipe(gulp.dest(distFolderUrl + '/static/css')) }) var jsList = [ './app/*.js', './app/src/directives/*.js', './app/src/controllers/*.js', './app/src/services/*.js', './app/src/filters/*.js', './tmp/templates/*.js', ]; gulp.task('jshint', function () { return gulp.src(jsList) .pipe(reload({stream: true, once: true})) .pipe(jshint()) .pipe(jshint.reporter('jshint-stylish')) }); // gulp.task('js', ['jshint'], function () { gulp.task('js', ['templatesTpls','templatesViews'], function () { return gulp.src(jsList) .pipe(concat('app.min.js')) .pipe(babel({ presets: ['es2015'] })) .pipe(uglify({ mangle: false,//类型:Boolean 默认:true 是否修改变量名 compress: false,//类型:Boolean 默认:true 是否彻底压缩 preserveComments: 'all' //保留注释 }).on('error', function(e){ console.log(e); })) .pipe(gulp.dest(distFolderUrl + '/static/js')) }); gulp.task('htmlVendor', function () { return gulp.src(['app/index-vendor.html']) .pipe(useref({ searchPath: ['app'] })) // .pipe(rename('index1.html')) .pipe(gulpif('*.js', uglify({ mangle: false, compress: false, preserveComments: 'all' }))) .pipe(gulpif('*.css', csso())) // .pipe(gulpif('*.html', htmlMinify({conditionals: true, loose: false}))) .pipe(gulp.dest(distFolderUrl)); }); // gulp.task('html', ['copyTemplatesToDist', 'copyTplsToDist'], function () { gulp.task('html', function () { return gulp.src(['app/index-dist.html']) .pipe(rename('index.html')) .pipe(gulp.dest(distFolderUrl)) }) gulp.task('build', ['public','vendor','js','css','html'], function () { return gulp.src(distFolderUrl + '/**/*').pipe($.size({title: 'build', gzip: true})); }); gulp.task('default', ['clean'], function () { gulp.start('build'); }); // var files = [ // 'app/**/*.html', // 'app/**/*.css', // 'app/**/*.js', // 'app/public/**/*', // 'app/data/**/*' // ]; gulp.task('serve', function () { browserSync({ notify: false, // Don't show any notifications in the browser. port: 8081, open: false, server: { baseDir: ['app'], routes: { // 'bower_components': 'bower_components',//if bower_components' path is up the tree of app }, middleware: function (req, res, next) { var urlObj = url.parse(req.url, true), method = req.method, paramObj = urlObj.query; mockApi(res, urlObj.pathname, paramObj, next); } } }); // watch for changes gulp.watch([ 'app/**/*.html', 'app/**/*.css', 'app/**/*.js', 'app/public/**/*', 'app/data/**/*' ]).on('change', reload); gulp.watch('app/src/**/*.less', ['styles', reload]); gulp.watch('bower.json', ['fonts', reload]); }); gulp.task('serve-release', function () { browserSync({ notify: false, port: 8081, server: { baseDir: [distFolderUrl] } }); });
gulp <taskName>
git
$ gulp clean #清空编译目录 $ gulp build #编译打包 $ gulp serve #开启开发环境服务器 http://localhost:8080 $ gulp serve-release #开启生产环境服务器 http://localhost:8081
项目源码:angular-gulp-bower-seedgithub