猫窝私语 — Makumo's Blog

玛酷猫的温馨小窝,记录生活点点滴滴。

@玛酷猫3 年前

12/21
14:37
其他

skrollr中的anchor-position

前段时间有个项目需要在页面上使用视差效果,第一时间就想到了老牌的skrollr.js,虽然作者在2014年就已经不在更新的,不过放到现在依旧是比较好用的一款,然而在应用中着实被anchors的relative mode坑了一小下,记录下。

absolute mode的代码格式为data-[offset]-[anchor]
relative mode的代码格式为data-[offset]-(viewport-anchor)-[element-anchor]
在项目中吧viewport和element搞反了,盯了半天才找到原因。顺便放下官方的anchor-position示意图

skrollr中的anchor-position

@玛酷猫3 年前

06/24
14:16
PHP

升级PHP8踩坑记

最近后台总是提示当前使用PHP(7.2)版本过低,建议升级7.4。看着着实难受,干脆直接升到8.0好了,免得过段时间又开始不停的弹提示。说干就干,作为一个懒人,本着能yum坚决不make的态度,先去查了下remi源里面,已经有了8.0的版本。

yum repolist all |grep php

没有remi源的话可以用下面命令添加

yum -y install https://mirrors.aliyun.com/remi/enterprise/remi-release-7.rpm

后面的就简单了

# 先卸载掉老的版本
yum remove php-*
# 切换PHP8的源
yum-config-manager --enable remi-php80
# 安装
yum install php-cli php-fpm php-mysqlnd php-zip php-devel php-gd php-mbstring php-curl php-xml php-pear php-bcmath php-json php-redis php-opcache

然后重启httpd,然后就是经典的报错了。。错误代码Invalid command ‘php_admin_value’。查了下站点的配置文件,使用的是如下配置

php_admin_value open_basedir "站点目录:/tmp/:/var/tmp/:/proc/"

这是将php作为httpd的一个module使用,为嘛使用这个已经无法考证了,估计八成多年前从哪抄来的。网上搜了下,基本都是说httpd缺少module,在编译的时候需要修改配置,加上–with-apxs2参数,要重新编译。我这是直接yum的,这个就跳过。此外还有更换调用方法,例如FastCGI模式,将php-fpm作为服务启动,httpd将.php的请求发送到php-fpm服务上。懒人理念直接跳过,google上翻了半天,终于找到了解决办法,一句话

yum install mod_php

这才对嘛,既然是yum安装的问题,肯定可以用yum的方法解决。重启httpd,已经正常启动,打开网站,500错误,意料之中,毕竟大版本升级。查看了下httpd的日志,某个10年前的插件中还存在这个函数create_function(),而货已经在8中被干掉了,直接删除了这个插件。刷新,页面轻松打开,重新查看了下日志,一大堆PHP Warning,都是插件的问题,这个就主要等着各位插件作者后续更新了。

升级PHP8踩坑记

@玛酷猫4 年前

06/10
11:46
其他

阿里云设置泛域名SSL证书

泛域名SSL证书首选还是Let’s Encrypt,之前小窝加装泛域名证书用的也是它,具体可以查看之前的文章小窝加装泛域名SSL证书,今天帮朋友的站点设置SSL证书,步骤不太一样,顺便记录一下。

首先还是要下载acme.sh,安装成功后断开重新连接下终端,要不会后续的命令提示找不到

curl https://get.acme.sh | sh

由于朋友的域名是在阿里云上面,操作和DNSPOD上有些区别,先登录阿里云,在产品与服务里面,找到监控与管理分类,再在里面点选访问控制,或者在产品与服务下面直接搜索RAM访问控制,进入后先在左边菜单人员管理——用户里面新建一个用户,新建用户成功后会显示该用户的AccessKey ID和AccessKey Secret,这时候一定要记录下这两个值,因为这个只显示一次,如果丢失的话只能重新新建用户。随后在用户列表新建的用户后面操作里面点选添加权限,在弹出的权限列表里面搜索解析
,然后选择AliyunDNSFullAccess,后面备注是管理云解析(DNS)的权限。添加后点最下面的确定就好。

随后回到服务器命令行,依次键入下面命令(修改成对应的参数)

export Ali_Key='之前记录下的AccessKey ID'
export Ali_Secret='之前记录下的AccessKey Secret'
acme.sh --issue -d xxxx.com -d *.xxxxx.com --dns dns_ali

等待执行完毕就好。后续的服务器端的配置就和之前文章所写类似。

顺便一提的是Let’s Encrypt有申请错误的限制,同一域名同一账号连续失败5次后会被暂停申请1个小时,之前忘了给RAM用户附加权限,提示添加txt校验域名失败,添加权限后,然后就出现如下提示

 Create new order error. Le_OrderFinalize not found. {
  "type": "urn:ietf:params:acme:error:rateLimited",
  "detail": "Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/",
  "status": 429
}

这个就是频繁提交失败后被服务器暂停申请了,等1个小时再试就好了。

阿里云设置泛域名SSL证书

@玛酷猫6 年前

02/16
16:33
其他

Ionic 3 升级 Ionic 4 迁移踩坑系列(四)

路由
Ionic4整体舍弃了Ionic3中的使用IonicPage设置路由地址的方法,而完全使用Angular的路由器(虽然在ionic3中也可以使用Angular路由,不过之前项目都是使用Ionic3的路由方法)
在初始化的项目结构目录里src/app/app-routing.module.ts文件,一个简单的结构类似下方:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PermissionGuard, WelcomeGuard } from './guard/';

const routes: Routes = [
  { path: '', redirectTo: '/welcome', pathMatch: 'full' },
  { path: '', canActivate: [PermissionGuard], children: [
    { path: 'app', loadChildren: './pages/tabs/tabs.module#TabsPageModule' },
  ]},
  { path: 'welcome', canActivate: [WelcomeGuard], loadChildren: './pages/welcome/welcome.module#WelcomePageModule' },
  { path: 'sign-in', loadChildren: './pages/sign-in/sign-in.module#SignInPageModule' }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

在这个简单结构中包含一个tabs主模块,一个欢迎页,一个登录认证页面。用户第一次访问时,由第一条路由配置导向欢迎页,在欢迎页的配置上有路由守卫(Route guards)的设置,用来判断是否第一次访问,如果不是则引导到主模块,在主模块上同样配置一个路由守卫,用来检验用户权限,如权限不正确则引导到登录页面。此外路由不仅可以配置在总的路由配置文件中,也可以配置在各级子模块中,一方面清晰模块关系,同时也方便模块的添加和移动。路由相关配置也有很多,详情可以参考官方文档,这里是传送门

路由守卫
在Ionic3中,使用ionViewCanEnter和ionViewCanLeave实现Route guards的功能,而在Ionic4中,由于使用Angular的路由,同样也使用其对应的路由接口,在官方文档中,有5种接口,分别是

CanActivate to mediate navigation to a route.
CanActivateChild to mediate navigation to a child route.
CanDeactivate to mediate navigation away from the current route.
Resolve to perform route data retrieval before route activation.
CanLoad to mediate navigation to a feature module loaded asynchronously.

在上面的例子中,使用了两个路由守卫用来判断是否第一次访问和是否具有用户权限,其中判断初次访问的例子如下

import { Injectable } from '@angular/core';
import { Router, CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router';
import { Storage } from '@ionic/storage';

@Injectable({
  providedIn: 'root'
})
export class WelcomeGuard implements CanActivate {

  constructor(public router: Router, private storage: Storage) {}

  async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    const first = await this.storage.get('firstIn');
    if (first) {
      this.router.navigateByUrl('app/tabs/(home:home)');
    }
    return !first;
  }
}

在路由守卫中判断本地存储中是否存在首次访问的标识,有的话就直接进入tabs模块的home子模块。更多详细用法,同样参见官网文档,传送门

Ionic 3 升级 Ionic 4 迁移踩坑系列(四)

@玛酷猫6 年前

01/10
14:39
Ionic(Angular)

Ionic 3 升级 Ionic 4 迁移踩坑系列(三)

接下来就是页面的迁移,先用命令创建原来项目对应的页面,例如登录页面

ionic g page pages/signIn

这是会在src/app/pages目录下面生成sign-in文件夹,里面包含5个文件,相对于Ionic3,除了文件名命名有些许区别外,同时还多了一个测试文件,对比下Ionic3的sign-in.ts和4的sign-in.page.ts文件的主体结构

# ionic3
import { Component, OnInit } from '@angular/core';
@IonicPage({
  segment: 'sign-in'
})
@Component({
  selector: 'page-sign-in',
  templateUrl: 'sign-in.html',
})
export class SignInPage implements OnInit {
  ngOnInit() {}
}

# inoic4
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
@Component({
  selector: 'app-sign-in',
  templateUrl: './sign-in.page.html',
  styleUrls: ['./sign-in.page.scss'],
  encapsulation: ViewEncapsulation.None
})
export class SignInPage implements OnInit {
  ngOnInit() {}
}

整体上差别不大,主要区别在@Component部分,选择器的命名,模板文件和样式文件的引用,3中的@IonicPage部分在4种移除,部分功能被放在Angular的路由中。此外特别提下encapsulation: ViewEncapsulation.None的问题,这部分我也没完全弄明白,大概理解是Ionic4使用了标准的Web Components,可以在页面上看到大量的shadow-dom,默认情况下,由于Angular提供的样式包装机制来封装组件,使得组件的样式不受外部影响,就是说无法修改组件的样式,所以这里要将封装模式调整成none,以便于修改组件的样式,详细说明请参考官方文档,传送门。此外由于使用标准Web Components,样式也要大量的使用CSS4 Variables的写法。

页面生命周期

在Ionic3中,常用的页面生命周期函数有下面6种

  • ionViewDidLoad 当页面加载的时候触发,仅在页面创建的时候触发一次,如果被缓存了,那么下次再打开这个页面则不会触发
  • ionViewWillEnter 当将要进入页面时触发
  • ionViewDidEnter 当进入页面时触发
  • ionViewWillLeave 当将要从页面离开时触发
  • ionViewDidLeave 离开页面时触发
  • ionViewWillUnload 当页面将要销毁同时页面上元素移除时触发

在Ionic4中,使用Angular的生命周期函数,具体ionViewDidLoad被ngOnInit替代,ionViewCanEnter和ionViewCanLeave被路由守卫替代,其他的暂时可以正常使用,不过可能在以后的版本中被其他用法做代替。

组件的标准化

由于使用Web Components标准,很多组件和属性的写法也发生变化,譬如

// ionic 3
<button type="button" ion-button clear small icon-start (click)="findPassword()" class="option-password">忘记密码</button>

<ion-list radio-group no-lines [(ngModel)]="schoolCode">
  <ion-item *ngFor="let s of schools">
    <ion-avatar item-start><img src="{{s.logo}}"></ion-avatar>
    <ion-label>{{s.name}}</ion-label>
    <ion-radio value="{{s.code}}"></ion-radio>
  </ion-item>
</ion-list>

// ionic 4
<ion-button type="button" fill="clear" size="small" (click)="findPassword()" class="option-password">忘记密码</ion-button>

<ion-list lines="none">
  <ion-radio-group [(ngModel)]="schoolCode">
    <ion-item *ngFor="let s of schools">
      <ion-avatar solt="start"><img [src]="s.logo" alt=""></ion-avatar>
      <ion-label>{{s.name}}</ion-label>
      <ion-radio [value]="s.code"></ion-radio>
    </ion-item>
  </ion-radio-group>
</ion-list>

除了button标签替换成ion-button以外,很多属性也发生变化,譬如button的所有属性都进行了更换,clear更换成fill=“clear”等,其他标签的属性,譬如item-start更换为solt=“start”,此外类似radio-group的用法也发生大变化。由于不少用法发生变化,具体还是对应着官方文档进行迁移,传送门

Ionic 3 升级 Ionic 4 迁移踩坑系列(三)

@玛酷猫6 年前

01/4
10:59
Ionic(Angular)

Ionic 3 升级 Ionic 4 迁移踩坑系列(二)

首先是更新NodeJS版本,Angular6要求版本不低于8.X,由于之前安装高版本的nodeJS一直有着不可描述的问题,导致node-sass无法安装,无奈只能安装6.X的版本使用本地文件来强行安装node-sass,不过现在貌似没这个问题了。更新也比较方便,卸掉重新安装就好了。
开启一个新的tab项目,详细的安装可以参考官方文档

ionic start myApp tabs --type=angular

provider迁移
项目建好后,先将原来项目中的provider复制到新项目中,这时候会看到满篇的错误提示,一个一个来调整。
1、storage在Ionic4中不再是默认自带,需要单独安装

npm install --save @ionic/storage

2、换用新的http模块

//ionic3 部分代码
import { Http, Headers, RequestOptions } from '@angular/http';
//……中间其他代码……
const headers = new Headers();
let Token: string = '';
headers.append('Token', Token);
this.options = new RequestOptions({ headers: headers });

//ionic4 部分代码
import { HttpClient, HttpHeaders } from '@angular/common/http';
//……中间其他代码……
const headers = new HttpHeaders();
let Token: string = '';
headers.set('Token', Token);
this.options = { headers };

由于需要和数据服务器API通讯,用户的信息token是存放在请求的header中,在Ionic3中使用的Headers, RequestOptions来处理请求头部,这两个组件在3中也属于不推荐使用的,当时因为还能用,图省事就继续使用了。4种更换为HttpClient、HttpHeaders,和以前方法使用变化不大,调整下就好。

3、调整Components用法,这部分也是整个项目变动最多的地方,几乎所有的Controller都有参数变动和使用方法的变动,想像迁移文档说的那样直接复制进来就能用基本没法实现。举个例子,项目中有个全局的顶部消息提示控件

//ionic3
toast(message: string) {
  this.toastCtrl.create({
    message: message,
    duration: 1500,
    position: 'top'
  }).present();
}

//ionic4
async toast(message: string) {
  const toast = await this.toastCtrl.create({
    message: message,
    duration: 1500,
    position: 'top'
  });
  toast.present();
}

在Ionic3中可以直接创建后接present()来触发使用,而在4中,需要配合async/await来使用。

4、RxJS的调整,官方有个迁移文档,传送门,并且给出了一个迁移工具,不过试了下不是太好用,可能原本的项目写的就不是很规范,只能自动修复一小部分。还是老老实实手动来吧,顺便加深下印象。以下是一个登录的代码片段

//ionic3
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
//……中间其他代码……
PostSignIn(request: PostUserSignInRequest): Observable<any> {
  return this.http.post(this.coreService.baseUrl + '/tokens', request)
    .map(res => res.json());
}

//ionic4
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
//……中间其他代码……
PostSignIn(request: PostUserSignInRequest): Observable<any> {
  return this.http.post(this.coreService.baseUrl + '/tokens', request)
  .pipe(map(res => res));
}

首先是引入调整,这个全项目批量替换下就好,然后是原来的链式操作(dot-chained operators)要更换为管道操作(pipeable operators),简单点说就是将原先所有的.xxx操作全部放置到pipe()这个方法中,其他的用法项目中用到的少,可以去查看官方文档。

Ionic 3 升级 Ionic 4 迁移踩坑系列(二)

@玛酷猫6 年前

01/3
23:01
WordPress 建站日志

小窝加装泛域名SSL证书

(本来打算写在上篇的,篇幅有点长,干脆拆成两篇好了)
书接上回,话说随着chrome的版本更新,所有的http访问的网站都会在网址前面标一个大大的不安全,这都9102年了,不给网站弄的SSL证书也太不像话了。免费证书哪家强,当然是选择Let’s Encrypt,而且今年去年年中的时候已经支持泛域名的证书,B格更高,同时也推出了新的申请方式,相对于以前单个域名的申请,方便很多。

首先要下载acme.sh,安装成功后断开重新连接下终端,要不会后续的命令提示找不到

curl https://get.acme.sh | sh

由于acme.sh可以自动配置DNS,这就需要获取到域名的API,我的域名是使用DNSPOD解析的,这里就用DNSPOD做例子,其他的请参考官方指南。登录DNSPOD,在控制台——用户中心——安全设置里面,启用API Token,创建新的API Token,这里一定要保存好Token,因为这个是只显示一次,关掉后就没法获取完整,只能删掉重新建,同时记下Token对应的ID,然后运行下面命令,等待120秒验证,屏幕上会显示倒计时,如果一切正常的话,屏幕会显示申请成功并显示4个证书文件的路径。

export DP_Id='ID数字'
export DP_Key='Token字符串'
acme.sh --issue -d makumo.com -d *.makumo.com --dns dns_dp

然后打开站点的Nginx的配置文件,添加相关的配置,例如:

server 
    {
        listen 443 http2 ssl;
        server_name makumo.com;
        index index.html index.php;
        root  站点目录;
        ssl_certificate /root/.acme.sh/makumo.com/fullchain.cer;
        ssl_certificate_key /root/.acme.sh/makumo.com/makumo.com.key;
        ssl_trusted_certificate  /root/.acme.sh/makumo.com/ca.cer;
        include proxy-pass-php.conf;
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }
        location ~ .*\.(js|css)?$
        {
            expires      12h;
        }
        location ~ /\.
        {
            deny all;
        }
}

proxy-pass-php.conf文件即为上一篇中的关于转发到Apache的部分.

nginx -s reload

重新加载Nginx配置文件就能使用https访问站点,这时候还会存在几个问题,站点中图片、脚本、样式还是使用的http来引入,在浏览器中会报出错误,后台无法进入,浏览器会显示过多的重定向,网络里面会看到一堆的302重定向,搜了下,绝大部分都会说在Wordpress配置文件中添加开启SSL的配置,如下:

$_SERVER['HTTPS'] = 'on';
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

但是我这么设置后,前台没问题了,后台还是无法进入,虽然不报过多的重定向,直接报403错误了。
搜素了半天,还在有更简便的解决方案,安装插件really-simple-ssl,一次性解决各种恶心的问题。
另外,由于站点使用七牛作为图片的CDN缓存,站点切换为https后也需要将七牛的CDN改成https模式,在七牛的后台添加下证书(之前申请证书的4个文件,fullchain.cer是证书,域名.key就是对应的密钥),关联域名开启SSL就好了,这也是泛域名证书的方便之处,不用再次申请单域名证书了。七牛的https是收费的,看了下,0.28元/G,之前还有赠送的10元余额。应该能用段时间。

小窝加装泛域名SSL证书

@玛酷猫6 年前

01/3
22:08
建站日志

小窝迁移升级

今天忽然收到阿里云的提示,个人的云服务器要到期了,连忙登录上去准备续费,一看价格,我勒个擦,8XX,当初买的时候才3XX,去年续费的时候5XX,这涨的也太快了,看了下新购,同样配置同一地区也才5XX,算了算了,还是重新购买台好了,虽然要重新配环境迁移网站麻烦点,谁让咱穷呢。

下单付款,等会就开通,ssh连上去,先配置下环境,之前那台服务器用的lnmp一键包,当初菜鸟一只啥都不会。现在基本了解了后,一键包方便是方便,但是问题也不少,首先就是文件的安装位置都变了,配置文件也和默认的不太一样,详细配置的时候各种别扭,其次就是带着一些不用的软件,还有就是版本升级的问题。所以还是自己配好了,好在CentOS配置起来比较简单,几行命令就好了。服务结构还是像往常那样,Nginx跑静态文件和代理,Apache跑PHP7,预配NodeJS和Ruby,平时做简单的调试用,通过Nginx转发访问

# 安装nginx
yum install nginx
# 由于yum源没有php7,所以要更换
yum install epel-release
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
# 安装php7.2以及相关扩展
yum install php72w php72w-cli php72w-common php72w-devel php72w-embedded php72w-fpm php72w-gd php72w-mbstring php72w-mysqlnd php72w-opcache php72w-pdo php72w-xml
# 安装mariadb
yum install mariadb mariadb-server
# 设置mariadb密码,需要先运行mariadb服务
mysql_secure_installation

新建站点和相关配置就不多说了,有几点要注意下,
1、httpd的默认配置文件里面,所有请求会全部拒绝,要删掉或者注释掉

<Directory />
    Options FollowSymLinks
    AllowOverride none
    Require all denied
</Directory>

2、站点的目录用户组要调整成为apache:apache

httpd服务的端口调整为88,在Nginx站点配置的时候,添加相关的配置说明,如下例子

location /
{
    try_files $uri @apache;
}
location @apache
{
    internal;
    proxy_pass http://127.0.0.1:88;
    include proxy.conf;
}

location ~ [^/]\.php(/|$)
{
    proxy_pass http://127.0.0.1:88;
    include proxy.conf;
}

proxy.conf里面存放一些代理设置

proxy_connect_timeout 300s;
proxy_send_timeout   900;
proxy_read_timeout   900;
proxy_buffer_size    32k;
proxy_buffers     4 32k;
proxy_busy_buffers_size 64k;
proxy_redirect     off;
proxy_hide_header  Vary;
proxy_set_header   Accept-Encoding '';
proxy_set_header   Host   $http_host;
proxy_set_header   Referer $http_referer;
proxy_set_header   Cookie $http_cookie;
proxy_set_header   X-Real-IP  $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header   X-Forwarded-Proto $scheme;

最后迁移站点文件、还原数据库,启动各服务并设置随系统启动,测试没问题后将域名切换过来就ok了。

systemctl enable nginx.service
systemctl enable httpd.service
systemctl enable maridb.service
systemctl start nginx.service
systemctl start httpd.service
systemctl start maridb.service

顺便一提的是本次迁移也干掉的www,www是个很奇怪的历史遗留的问题,这是个二级域名,可能很多人认为方便呀,直接ctrl+enter就自动补全了,可是最早的IE浏览器直接ctrl+enter的话补全的是www.xxx.cn.co而并不是www.xxx.com,方便无从谈起,直到后续大量的国产带壳浏览器的出现才修正过来,况且那时候.net域名还是很流行的,还有不少.cn的域名,而且大部分人都不会直接打域名来访问网站,基本上都是打开百度搜索网站,要不就是收藏夹或者聚合网址来上网。所以www就是多余的,去掉后网址还精简一些。虽然去掉www会影响搜索引擎的搜录,好在小窝文章本来就不多,写的也是断断续续的,大部分都是方便自己以后查找用的,也不在乎那点收录了。

小窝迁移升级

@玛酷猫6 年前

12/28
16:31
Ionic(Angular)

Ionic 3 升级 Ionic 4 迁移踩坑系列(一)

Angular今年的发展真是快,去年年底5刚刚发布,年中就发布6,到年底7也来了,大版本的升级也导致它的很多组件也随之升级,慢慢的放弃了对低版本的支持,这对于使用基于Angular的Ionic开发的本人来说就是件很郁闷的事情。之前一直使用Ionic 3开发项目,还是基于Angular5的,年中的时候本地开发环境更新组件没注意,直接把Angular升级到6了,然后可想而知,项目直接跑不起来了。还原package.json后每次更新组件都检查下版本,避免错误升级,很是麻烦。随着Ionic4的测试版本不断的更新,Ionic cli动不动就提示更新Ionic4,稍不留神就傻逼,再加上越来越多的组件默认使用Angular 6,主要是其中RxJS的语法变动很大,导致没法向下兼容5,这也将Ionic升级到4的想法提上日程。毕竟ios和android还在不停的更新版本,每次更新或多或少都会出现兼容性问题,组件导致的兼容性问题主要还是靠组件作者更新,虽然可以自己fork一个分支处理,毕竟费时费力。

去Ionic官网翻了翻迁移指南,官方写的实在是太简单,全文如下:

  1. Generate a new project using the blank starter (see Starting an App)
  2. Copy any Angular services from src/providers to src/app/services
    • Services should include { providedIn: ‘root’ } in the @Injectable() decorator. For details, please see Angular provider docs.
  3. Copy the app’s other root level items (pipes, components, etc) keeping in mind that the directory structure changes from src/components to src/app/components, etc.
  4. Copy global Sass styling from src/app/app.scss to src/global.scss
  5. Copy the rest of the application, page by page or feature by feature, keeping the following items in mind:
    • Emulated Shadow DOM is turned on by default
    • Page/component Sass should no longer be wrapped in the page/component tag and should use Angular’s styleUrls option of the @Component decorator
    • RxJS has been updated from v5 to v6 (see RxJS Changes)
    • Certain lifecycle hooks should be replaced by Angular’s hooks (see Lifecycle Events)
    • Markup changes may be required (migration tool available, see Markup Changes)

In many cases, using the Ionic CLI to generate a new object and then copying the code also works very well.

大概意思就是用命令新建一个空的项目,将原来项目各个部分拷贝进来,注意4的路径有所调整。服务的声明有所调整、全局样式文件不一样、RxJS请自己看升级文档、页面生命周期时间沿用Angular。看来不麻烦呀,于是乎我就傻呵呵的按着文档操作一顿后,都不用试跑的,IDE上满屏幕的红色波浪线(各种错误)仿佛在嘲笑。看了看IDE上面提示的各种错误,连最基本的ionic、angular的引用方式都有所变化,我就不信有人能按照这个智障的迁移文档,把项目跑起来。尤其是看到文档最后一句话:“In many cases, using the Ionic CLI to generate a new object and then copying the code also works very well. ”,还信誓旦旦的说大部分情况下按照这个操作项目都能跑起来,我&……¥&*……&#,还是老老实实一个模块一个页面的迁移好了。

经历的大半个月的迁移工作,虽说还没有完全结束,迁移过程中踩的坑可真不少,准备做一个系列来写了。一方面记录下的这些问题,方便以后查看,另一方面也希望帮助其他的人,毕竟目前在国内,相对于React和Vue,Angular还太小众,各种文档和解决方案都很少,遇到问题都要爬google搜索,要不就去啃官方论坛和stackoverflow。

随带一提的是Ionic(Angular)的发展简直是坑神一样的存在,当年AngularJs升级Angular(ionic1到2)的时候,惊呼上当受骗,本以为是个版本升级,能迁移的时候菜发现这明明就是两种不同的东西,没办法相当于重新学了一遍,ionic2/3到4又相当于再重学一边,4为了更标准化web component,修正了以前版本各种不标准的用法和属性,而且可以说不在依赖框架,也就是说以前Ionic和Angular是捆绑在一起的,从4版本开始,也可以使用React和Vue来做开发,更加灵活。并且使用标准化的web component后,以后也不会出现类似1到2、2/3到4这种痛苦的迁移过程了,应该会很平滑的升级,版本迭代的速度应该会更快。

Ionic 3 升级 Ionic 4 迁移踩坑系列(一)

@玛酷猫7 年前

03/23
15:12
Ruby

Rails5踩坑系列——Vagrant和NFS共享文件夹

新年新项目,被老项目折腾大半年后,部门一直认为新项目要脱离老的Rails3.2版本,拥抱新版本。先准备前期环境,对应的安装了最新的Ruby2.5和Rails5.1.5,开始项目后台框架搭建工作。同事用vm搭建的虚拟机环境,没啥问题,我是用的Vagrant搭建的虚拟机环境,由于Vagrant自身共享模式很慢,一直配置着vagrant-winnfsd插件使用NFS来做文件共享,速度是快很多,就是经常性会遇到I/O错误,关掉日志防止频繁写入共享盘就好了。新项目跑起来就开始报错,报错信息类似如下

Errno::EEXIST at / File exists @ dir_s_mkdir - tmp/cache/assets/sprockets/v3.0/jG

网上搜了一下,发现一篇博文说到这个,传送门,大体意思就是NFS是大小写不明感,rails在运行中会将assets生成静态文件缓存,存在tmp/cache/assets/sprockets/v3.0/ 目录中,文件按照前两位字母建立文件夹归档,这时候就会遇到类似jg、JG、jG、Jg属于4个不同文件夹,但是NFS大小写不明感,就会认为是一个,在创建的时候就会返回文件夹已存在的问题,文中给出的方案是修改配置文件,将这个文件移出共享文件夹。由于不想将虚拟机原始文件系统里面放置额外的文件,这个方案被我否定了。查了下原来项目里面老版本文件缓存情况,类似的结构和生成方式,不过生成的文件缓存文件名都是大写,文件夹也都是大写,就不存在大小写的问题。本想找办法对应修改下,翻了下Asset Pipeline相关文档和sprockets的相关配置,都没有找到,遂放弃这个办法。在查看文档中,有关于静态资源文件缓存的存储方式的说明,默认似乎是文件方式,文档给出的修改例子是内存方式,于是在development.rb中添加这个配置,重启项目,一切OK。下面的禁用方式也试了下,影响速度还是很明显,同样不考虑。

此外上述文中还提到了其他几种由于NFS大小写不明感而引起的问题以及处理办法,目前暂时还没遇到。下次遇到了也心里有数了。

Rails5踩坑系列——Vagrant和NFS共享文件夹