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

在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);

2) 项目结构详细说明:

  • src中的项目结构:

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

  • js目录中的项目结构:

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

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

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

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

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

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

这种方式使用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
  • 根目录中的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"
    }
    

    可见这里做了三组跨域设置,一个是用户中心,一个是短信接口,一个是提供基本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'
         }
     }
    

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'); // 压缩html
var cleanCSS = require('gulp-clean-css');
var uglify = require('gulp-uglify'); // 压缩js
var _if = require('gulp-if'); // 引用判断
var del = require('del'); // 清空文件和文件夹
var stripDebug = require('gulp-strip-debug'); // Strip console, alert, and debugger statements
var 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 task
var 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 task
gulp.task('clean', function () {
    return del([
        paths.dist + '/**/*'
    ]);
});

// copy src to www
gulp.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 file
function 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 files
gulp.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 sass
gulp.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 dist
gulp.task('imagemin', function () {
    gulp.src(paths.images)
        .pipe(plumber())
        .pipe(imagemin())
        .pipe(gulp.dest(paths.dist + '/images'));
});

// copy fonts task
gulp.task('copy-fonts', function () {
    return gulp.src(paths.fonts)
        .pipe(plumber())
        .pipe(gulp.dest(paths.dist + '/fonts'));
});

// minify third library script 第三方不用去 stripDebug
gulp.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 task
gulp.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 task
gulp.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 task
gulp.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();
});

扩展

IONIC 功能全演示 ===================== - 使用Ionic提供的UI 组件。Ionic本身是致力于建立统一的移动混合app构建平台,核心基础是Angular+Cordova。 - 通过Angular指令封装,以及预定义的CSS,提供了开箱即用的HTML5 Mobile组件。 - 构建与开发支持,能够直接运行www目录下的index.html进行开发调试。同时也支持发布人员利用gulp构建输出到dist目录 - 利用gulp,同样演示了单元测试以及场景测试。 - [在线演示,内有地址二维码,可手机浏览](http://1.thm1118.sinaapp.com/static/ionic/www/index.html) ## 预览 ![信息卡片](screenshot/card.png) ![下拉刷新](screenshot/pullrefress.png) ![表单元素](screenshot/form.png) ![菜单](screenshot/menu.png) ![列表左滑按钮](screenshot/option.png) ![弹出层](screenshot/pop.png) ![tab](screenshot/tab.png) ![幻灯](screenshot/slide.png) ![图片水平滚动](screenshot/hscroll.png) ![毛玻璃效果](screenshot/blure.png) ![2000条数据搜索](screenshot/search.png) ![输入自动完成](screenshot/autocomplete.png) ![列表自动分组](screenshot/autogroup.png) ![媒体相册](screenshot/galaxy.png) ![chartjs统计图](screenshot/chartjs.png) ![百度统计图](screenshot/echat.png) ![图片延时加载](screenshot/imageload.png) ## 基础环境 纯webapp运行或演示,只需要一个 web server部署即可。 ## 目录结构说明 - www 目录:源码目录 - dist目录:构建输出目录 ## 利于开发,测试和打包部署的nodejs环境 简单开发可以不依赖nodejs环境。但是有了基于nodejs的javascript完整开发周期环境,会极大提升开发效率,保障质量。 - nodejs 最新版。 - 有些node包的安装需要c++编译,x86版本只需要 x86的C++编译器,windows上的x64 c++编译器需要特别设置。 - npm 会很慢,要么使用代理,要么使用国内镜像,比如 [淘宝镜像](http://npm.taobao.org/) , 使用淘宝镜像后,npm命令需要替换成cnpm命令。 - `npm install -g gulp` - `npm install -g ionic` - 如需编译sass的话,安装 [ruby](https://www.ruby-lang.org/zh_cn/),再执行 `gem install sass`(如遇到ssl错误,修改为http源:gem source -a http://rubygems.org/) - `npm install -g node-gyp` - 有的node包依赖python编译,安装 [python2.7](https://www.python.org/) - c++编译环境[MSVStudio 免费版](https://www.visualstudio.com/downloads/download-visual-studio-vs#d-express-windows-desktop).。注意根据studio不同版本指定 --msvs_version=2013 选项 - 安装项目开发依赖包,在项目根目录下运行 `npm install` ### “所见即所得”式开发 - 在项目根目录下运行 `ionic serve`,即可在www目录下开展“所见即所得”的方式开发 - 另外一种方式,在webstorm里对index.html 按debug运行,同样是“所见即所得”的方式开发 ### CROS支持 - 生产环境的 CROS支持要么使用jsonp技术,要么在服务端设置代理。 - 而开发环境下要么 基于不安全做法,服务端api 设置头`Access-Control-Allow-Origin:*" `,要么按如下便捷设置: 基于`ionic serve`, 可以在开发时使用本地代理。ionic.project 内设
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值