从ionic的项目构建和跨域设置说起

来源:互联网 发布:中介软件哪个好 编辑:程序博客网 时间:2024/05/18 05:52


在ionic1中使用gulp进行项目构建,在ionic2中引入了webpack, 使用ionic2的webpack需要修改相关的配置,而在ionic1中需要自己写gulp任务。其中有一篇特别有帮助的文章, github地址,上面的内容只作为借鉴。这里只叙述下ionic1的,因为比较繁琐。本文只提供一下思路,而非具体步骤。Just a clue, not steps!

相关项目结构

  • 源码src目录
  • 拷贝或编译后的代码www目录

两个环境

  • 开发环境 
  • 生产环境 
  • 备注:个人感觉没有必要用原文中的staging环境,还有demo中有很多没用的任务, 还有一些是让你Todo的。其中有关api-config的可能是做跨域的,也没有用到,本文用的是ionic-cli

注意事项

1) 其中每个模块的写法都是直接挂载到ng-app上的,所以每个模块不需要注入,但必须先引入app.js文件,所以就有了上述boot的任务。 
如下一个controller模块 : 

(function (angular) {    'use strict';    angular.module('yourNgAppName')        .controller('homeCtrl', [            '$scope',            function ($scope) {                // your business logic            }]);})(angular);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2) 项目结构详细说明:

  • src中的项目结构: 

        这里写图片描述  
        
      其中components中是自己的业务代码,比如主页模块,分类模块,tab模块等。

  • js目录中的项目结构: 

      这里写图片描述 
      
    其中api提供单纯api模块,app包括项目中的启动文件,通用服务,通用指令,全局变量和app.templates.js文件。settings 文件夹中主要包括设置中通用设置,网络相关设置,匿名ip用户功能,和通用方法组件。third中提供基于cordova的一些第三方功能如QQ,微信,微博登陆功能和极光推送功能等。(备注: 这些设置都是根据自己需求来做的)

3) app.templates.js 文件用法。

 angular.module("templates", []);
  • 1

将templates模块注入到app.js中作为主要依赖。而在名为templates的gulp任务的中将所有的view层写入到缓存模版中。

4) 文件注入, gulp 任务中的inject任务,关键代码:

.pipe(inject(gulp.src(paths.css, {read: false}), {starttag: '<!-- inject:css:{{ext}} -->', relative: true}))
  • 1

这种方式使用tag标记和relative:true属性来注入自己的文件。relative表示是否使用相对的路径。

5)跨域相关:

  • ionic 内部提供了一个跨域工具就是ionic-cli, 官方文档上有说明。这里用的版本是:

    • "@ionic/cli-plugin-gulp": "1.0.1",
    • "@ionic/cli-plugin-ionic1": "2.0.0"
  • 备注】此处是博客补充,修改时间为:2017年8月26日 22:30:34,在CLI 3.8版本之后将不用这两个插件了,由此这两款插件可以不用安装了,具体提示信息如下:

    [WARN] Detected @ionic/cli-plugin-ionic1 in your package.json.As of CLI 3.8, it is no longer needed. You can uninstall it:npm uninstall --save-dev --save-exact @ionic/cli-plugin-ionic1[WARN] Detected @ionic/cli-plugin-gulp in your package.json.As of CLI 3.8, it is no longer needed. You can uninstall it:npm uninstall --save-dev --save-exact @ionic/cli-plugin-gulp
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 根目录中的ionic.config.json文件中的设置:

     {    "name": "your-app-name",    "app_id": "your-app-id",    "gulpStartupTasks": [        "watch"    ],    "watchPatterns": [        "www/*"    ],    "proxies": [        {            "path": "/api/user",            "proxyUrl": "http://xx.xx.xx.x1:8080/api/user"        },        {            "path": "/api/sms",            "proxyUrl": "http://xx.xx.xx.x1:8080/api/sms"        },        {            "path": "/api",            "proxyUrl": "http://xx.xx.xx.x2:8082/api"        }    ],    "type": "ionic1"}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    可见这里做了三组跨域设置,一个是用户中心,一个是短信接口,一个是提供基本api接口。

    在全局变量中的主要设置如下(关键代码):

    if (window.cordova) {     return {         base: 'http://xx.xx.xx.x2:8082/api',         user: 'http://xx.xx.xx.x1:8080/api'     } } else {     return {         base: 'http://localhost:8100/api',         user: 'http://localhost:8100/api'     } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

6) 开发模式:

  • 执行$ gulp dev 或者 gulp build --env dev
  • 稍后片刻,当打开浏览器后, 在项目目录下新开终端,执行监视拷贝任务 $ gulp watch
  • 当在监视任务执行中时, 就可以进行我们的开发了。修改src中的文件,自动同步到www目录,www目录一旦改变,就会通过ionic-cli刷新了浏览器。
  • 注意,此处开了两个终端(或命令行),一个用于跨域和刷新,一个用于监视。如果偶尔出现问题,重新运行任务即可。

7) 生产模式:

  • 执行:$ gulp pro 或者 gulp build --env pro
  • 执行完毕就可以在www目录中得到压缩,混淆合并后的代码了。

8) 其他相关:

  • 关于bower第三方管理,可见上述是直接写入gulp文件的,存在局限性,但是有些包的规则并不都是在dist目录中的,所以使用这种方式直接了当。网上很多其他bower管理相关插件,这里没用到。
  • 当然其他还有更好的优化这个工作流,比如一些css的进一步优化等。

gulpfile参考代码

var gulp = require('gulp');var gutil = require('gulp-util');var bower = require('bower');var concat = require('gulp-concat');var sass = require('gulp-sass');var rename = require('gulp-rename');var ngAnnotate = require('gulp-ng-annotate');var imagemin = require('gulp-imagemin'); // 压缩图片var htmlmin = require('gulp-htmlmin'); // 压缩htmlvar cleanCSS = require('gulp-clean-css');var uglify = require('gulp-uglify'); // 压缩jsvar _if = require('gulp-if'); // 引用判断var del = require('del'); // 清空文件和文件夹var stripDebug = require('gulp-strip-debug'); // Strip console, alert, and debugger statementsvar sh = require('shelljs');var watch = require('gulp-watch');var plumber = require('gulp-plumber');// Linting Sass stylesheets with Stylelint// http://www.creativenightly.com/2016/02/How-to-lint-your-css-with-stylelint/var postcss = require('gulp-postcss');var reporter = require('postcss-reporter');var syntax_scss = require('postcss-scss');var stylelint = require('stylelint');var ngConstant = require('gulp-ng-constant');var extend = require('gulp-extend');var args = require('yargs').argv;var templateCache = require('gulp-angular-templatecache');var inject = require('gulp-inject');var htmlreplace = require('gulp-html-replace');// This is intended to be a temporary solution until the release of gulp 4.0 which has support// for defining task dependencies in series or in parallel.var runSequence = require('run-sequence');var process = require('process');// === PATHS ===var paths = {    html: ['./src/*.html'],    css: ['./src/lib/ionic/release/css/ionic.css', './src/css/**/*'],    sass: ['./src/css/scss/*.scss'],    templates: ['./src/components/**/*.html'],    images: ['./src/images/**/*'],    fonts: ['./src/fonts/**/*', './src/lib/ionic/release/fonts/**/*'],    boot: ['./src/js/app/app.js'],    js: ['./src/js/**/*.js', '!./src/js/app/app.js'],    components: ['./src/components/**/*.js'],    scripts: ['./src/js/**/*.js', './src/components/**/*.js', '!./src/js/app/app.js', '!./src/js/app/app.templates.js'],    dist: ['./www'],    lib: [        './src/lib/ionic/release/js/ionic.bundle.js',        './src/lib/ngCordova/dist/ng-cordova.min.js',        './src/lib/ionic-native-transitions/dist/ionic-native-transitions.min.js',        './src/lib/angular-cookies/angular-cookies.js',        './src/lib/ionic-image-lazy-load/ionic-image-lazy-load.js'    ],    inject: [        './src/lib/ionic/release/css/ionic.css',        './src/css/**/*',        './src/js/**/*.js',        './src/components/**/*.js'    ],    watch: ['./src/**/*']};// ============ TOP LEVEL TASKS (invoke with "gulp <task-name>") ============// production taskvar productionTask = ['index', 'boot', 'scripts', 'minify-third-library-js', 'templates', 'copy-fonts', 'css', 'imagemin'];// 开发模式gulp.task('dev', ['clean', 'inject'], function () {    runSequence(        'copy-src-to-www',        function () {            gutil.log(gutil.colors.yellow('正在为您打开浏览器, 请稍后!'));            sh.exec('ionic serve');            // 本想打开一个新终端窗口去watch, 在同一目录下 ionic serve 和 watch 冲突。            // 所以现在解决方案是:手动打开新窗口切换到项目目录下执行 `gulp watch`        });});// 生产模式gulp.task('pro', ['clean'], function () {    gutil.log(gutil.colors.yellow('构建开始!'));    runSequence(productionTask, function () {        gutil.log(gutil.colors.yellow('构建完成!'));    });});// 或者使用一种方式开做开发模式和生产模式gulp.task('build', function () {    if (!args.env || (args.env === "dev")) {        runSequence('dev');    } else if (args.env && args.env === "pro") {        runSequence('pro');    } else {        gutil.log(gutil.colors.yellow('Wong arguments! Please check again!'));    }});// ==================================== children TASKS ====================================// clean taskgulp.task('clean', function () {    return del([        paths.dist + '/**/*'    ]);});// copy src to wwwgulp.task('copy', function () {    return gulp.src(paths.watch)        .pipe(plumber())        .pipe(gulp.dest(paths.dist + '/'));});// 监视src文件中的变化function handleWatchType(type) {    if (!type) {        return;    }    if (type === 'add' || type === 'unlink') {        injectFunc(); // 添加新文件 或 删除文件    }    // 备注 change 不做处理}gulp.task('watch', function () {    gulp.src(paths.watch)        .pipe(plumber())        .pipe(watch(paths.watch, function (vinyl) {            handleWatchType(vinyl.event);        }))        .pipe(gulp.dest(paths.dist + '/'))});// automatic injection third library script in the index filefunction injectFunc() {    return gulp.src('./src/index.html')        .pipe(plumber())        .pipe(inject(gulp.src(paths.css, {read: false}), {starttag: '<!-- inject:css:{{ext}} -->', relative: true}))        .pipe(inject(gulp.src(paths.lib, {read: false}), {starttag: '<!-- inject:lib:{{ext}} -->', relative: true}))        .pipe(inject(gulp.src(paths.boot, {read: false}), {starttag: '<!-- inject:boot:{{ext}} -->', relative: true}))        .pipe(inject(gulp.src(paths.js, {read: false}), {starttag: '<!-- inject:js:{{ext}} -->', relative: true}))        .pipe(inject(gulp.src(paths.components, {read: false}), {            starttag: '<!-- inject:components:{{ext}} -->',            relative: true        }))        .pipe(gulp.dest('./src/'))}gulp.task('inject', injectFunc);// prepare Index.html for dist - ie. using min filesgulp.task('index', function () {    gulp.src(paths.html)        .pipe(plumber())        .pipe(htmlreplace({            'css': 'css/app.min.css',            'boot': 'js/app.boot.min.js',            'js': 'js/app.bundle.min.js',            'third-library-js': 'js/app.plugin.min.js',            'templates': 'js/app.templates.min.js'        }))        .pipe(htmlmin({collapseWhitespace: true}))        .pipe(gulp.dest(paths.dist + '/.'));});// css task including sassgulp.task('css', function () {    gulp.src(paths.css)        .pipe(plumber())        .pipe(_if('*.scss', sass.sync()))        .pipe(cleanCSS({rebase: false}))        .pipe(concat('app.min.css'))        .pipe(gulp.dest(paths.dist + '/css'));});// imagemin images and output them in distgulp.task('imagemin', function () {    gulp.src(paths.images)        .pipe(plumber())        .pipe(imagemin())        .pipe(gulp.dest(paths.dist + '/images'));});// copy fonts taskgulp.task('copy-fonts', function () {    return gulp.src(paths.fonts)        .pipe(plumber())        .pipe(gulp.dest(paths.dist + '/fonts'));});// minify third library script 第三方不用去 stripDebuggulp.task('minify-third-library-js', function () {    gulp.src(paths.lib)        .pipe(plumber())        .pipe(ngAnnotate())        .pipe(uglify())        .pipe(concat('app.plugin.min.js'))        .pipe(gulp.dest(paths.dist + '/js'));});// boot taskgulp.task('boot', function () {    gulp.src(paths.boot)        .pipe(plumber())        .pipe(stripDebug())        .pipe(ngAnnotate())        .pipe(uglify())        .pipe(concat('app.boot.min.js'))        .pipe(gulp.dest(paths.dist + '/js'));});// scripts taskgulp.task('scripts', function () {    gulp.src(paths.scripts)        .pipe(plumber())        .pipe(stripDebug())        .pipe(ngAnnotate())        .pipe(uglify())        .pipe(concat('app.bundle.min.js'))        .pipe(gulp.dest(paths.dist + '/js'));});// templatesCache taskgulp.task('templates', function () {    gulp.src(paths.templates)        .pipe(plumber())        .pipe(htmlmin({collapseWhitespace: true}))        .pipe(templateCache({            standalone: true,            root: 'components'        }))        .pipe(uglify())        .pipe(concat('app.templates.min.js'))        .pipe(gulp.dest(paths.dist + '/js'));});// === OTHER TASKS (used by Ionic CLI default) ===gulp.task('install', ['git-check'], function () {    return bower.commands.install()        .on('log', function (data) {            gutil.log('bower', gutil.colors.cyan(data.id), data.message);        });});gulp.task('git-check', function (done) {    if (!sh.which('git')) {        console.log(            '  ' + gutil.colors.red('Git is not installed.'),            '\n  Git, the version control system, is required to download Ionic.',            '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',            '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'        );        process.exit(1);    }    done && done();});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259

扩展

  • 这篇文章确实很有帮助,关于前端架构,模块化不仅仅是为了重用,最重要的是分治
  • https://github.com/fouber/blog/issues/10
原创粉丝点击