本文重點是詳細介紹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