jenkins根据参数执行指定shell命令
为方便微前端部署的打包流程,特引入jenkins实现自动化部署,jenkins依据配置自动从用户指定的git远程仓库中拉取代码,并按配置执行打包部署等动作,单页面应用部署过程主要流程为(此处不对jenkins的安装和插件的选用做过多的介绍): 1、jenkins配置项目远程git仓库,实现构建时自动拉取对应仓库分支代码 2、编写构建时所需要的使用到的shell代码,例如安装环境,执行打包等命令(单个shell命令块中的命令按顺序执行,前一指令未完成不会执行后面的指令) 3、可使用构建后操作将shell命令打包之后的文件部署到所需服务器的项目位置(若部署服务器和jenkins在一起也可以使用shell命令移动部署文件进行部署)以上流程为单页面或其他项目的大概部署流程,本文主要记录的是微前端如何按需进行构建打包的流程。 一、jenkins所使用的的主要插件 1、Git:git插件主要用于获取git远程仓库的代码,同步到服务器中,测试时代码被同步到服务器的地址为 /var/lib/jenkins/workspace 2、Extended Choice Parameter:该插件为参数化构建过程中使用到的插件,目前只使用到该插件的Base Parameter Types的功能,插件大概使用的方式参考下图
服务器部署nodejs、nginx
部署和安装node、nginx 先安装node 1、下载对应的二进制文件 wget -c https://nodejs.org/dist/v8.9.1/node-v8.9.1-linux-x64.tar.xz 2、提取文件 tar -xvf node-v8.9.1-linux-x64.tar.xz 3、解压之后得到的文件就是安装好的nodejs了,为了方便我们可以对它重命名下 mv node-v8.9.1-linux-x64 /app/node 4、node和npm只能在/app/node/bin文件夹下使用,想要node和npm全局有效,可以通过创建软连接 ln -s /app/node/bin/node /usr/local/bin/node ln -s /app/node/bin/npm /usr/local/bin/npm 现在node和npm可以全局使用了,同样输入命令node -v来检查nodejs是否安装成功 安装常用node包 npm i pm2 webpack vue-cli -g 安装nginx 1、yum安装 yum install -y nginx 安装完成使用nginx -v检查是否成功,若出现以下输出则安装成功 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful 2、启动nginx systemctl start nginx.service // 启动nginx systemctl stop nginx.service // 停止nginx systemctl restart nginx.service // 重启nginx systemctl enable nginx.service // 设置开机启动部署线上vue项目 在usr/share目录下用mkdir创建www文件夹,创建app.js启动文件,const fs = require('fs'); const path = require('path'); const express = require('express'); const app = express(); app.use(express.static(path.resolve(__dirname, './dist'))); app.get('*',function(req,res){ const html = fs.readFileSync(path.resolve(__dirname, './dist/index.html'),'utf-8'); res.send(html); }) app.listen(8082) 代码在这就不做解释,这里主要讲解如何部署项目环境 由于我们使用了express框架,所以我们可以生成一个package.json,将依赖项添加进去{ "name":"vue-resume-dist", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "express": "^4.15.3" } } 然后将项目通过软件传到你需要的目录下,如果你是通过xshell上传的zip压缩包可以用unzip xxx.zip命令解压文件,如果是其他类型的压缩文件请自行搜索解压命令 之后通过命令cd到你的项目下进行npm install安装依赖,然后pm2 start app.js就成功启动服务了现在通过ip加端口形式就能正常访问,但是如果想通过域名访问就需要配置nginx映射nginx端口映射配置 首先你需要把一个二级域名解析到你的主机IP,比如我使用的vultr.zwight.net这个二级域名 解析域名(示例为万网域名解析): 1、先将二级域名解析到主机IP 在一级域名的解析列表添加一条新的解析记录,记录类型为A,主机记录为你的二级域名格式为 xxx(自定义的字符).zwight.net(一级域名),解析线路默认,记录值为你的主机IP; 这个二级域名访问网页除了默认的80端口(http)或者443(https)之外访问其他端口都需要二级域名+端口访问,若你需要在访问地址上不想出现端口号则可以通过域名的隐性URL解析到其他地址 2、隐性URL解析: 在解析列表添加一条新的解析记录,记录类型选择 隐性URL,主机记录还是xxx(自定义的字符,需要和二级域名不一致).zwight.net(一级域名),记录值则是二级域名+端口号(比如我的端口号为8080则填入:http://vultr.zwight.net:8080) nginx配置 将下面的配置放入etc/nginx的nginx.conf文件中,其中的端口和server_name改为自己的配置,server_name为你的二级域名upstream resume{ server 127.0.0.1:8082; } server { listen 8080; server_name vultr.zwight.net; location / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Nginx-proxy true; proxy_pass http://resume; proxy_redirect off; } }执行nginx -s reload重启nginx服务器
浏览器不同标签页间通信
前段时间由于有个项目可能需要两个屏幕的页面能实时通信,考虑到websocket需要服务端支持,存在不稳定性,因此项目中两个屏幕采用同一个主机控制,两个屏幕打开的页面属于同一个项目,只是通过两个标签页打开,所以探讨了不同浏览器标签页或者窗口发送数据的不同方法。 BroadCastChannel API 目前web api中有一个新的api为BroadCastChannel API,该API从Chrome54和其他几个浏览器的最新版本开始提供,其作用是允许来自同源的不同浏览器上下文(即窗口,标签等)之间的简单的通信,以下是使用该API的实例: let channel = new BroadcastChannel('channel-name'); 我们使用BroadCastChannel构造函数创建一个新通道,该构造函数接受频道的名称作为参数。频道名称很重要,因为正在侦听相同频道名称的频道间能够相互广播消息。通道可以从不同的标签页、工作程序和其他浏览器上下文中实例化,但只要他们正在侦听相同的通道名称,他们就能够相互通信。 使用频道广播消息,我们将调用postMessage()接收任何类型的参数进行广播消息: channel.postMessage('some message'); channel.postMessage({key:'value'}); 这将向正在侦听相同频道名称的所有其他频道发送消息,然后频道可以为此事件添加事件处理程序,以获取广播的消息: channel.onmessage = function(e){ const message = e.data; } 我们还可以通过关闭它来使通道停止接收消息: channel.close(); 理想情况下,BroadCastChannel API是实现跨标签页进行通信时的方法,它不仅可以跨标签页广播数据,还可以在其他浏览环境中广播数据,还包括iframe等。但是这个API相对较新,只有一些较新版本的主流浏览器能支持,因此使用时需注意版本的兼容问题。 SharedWorker API Local Storage
angular2+创建宿主视图(动态组件)
创建动态组件前先需要了解一个名词ViewRef,ViewRef表示一个angular视图,在angular中视图(View)是应用程序UI的基本构件。angular鼓励开发人员将UI看作是视图的组成,而不是独立的html标记树。 Angular支持两种视图Embedded Views which are linked to a Template(连接到模板的嵌入式视图) -----连接到模板的嵌入视图,在组件模板元素中添加模板(DOM元素、DOM元素组)Host Views which are linked to a Component(连接到组建的宿主视图) -----连接到组件的嵌入视图,在组件元素中添加别的组件 目前我们只讨论创建宿主视图。Creating host view(创建宿主视图) 当组件被动态实例化时,会创建宿主视图,使用ComponentFactoryResolver 可以动态的创建一个组件。 在angular中每个组件都要被绑定到一个注入器(inject)的特定实例,因此我们在创建组件时传递当前的注入器实例,而且需要将动态实例化的组件添加到模块或托管组件的EnterComponents中。视图创建完毕后我们可以使用ViewContainer将其插入到DOM中。ViewContainerRef 表示一个容器,其中可以附加一个或多个视图。 这里要提到的第一件事是,任何DOM元素都可以用作视图容器。有趣的是,Angular 在元素内部没有插入视图,而是在元素绑定到 ViewContainer 之后附加它们。这类似于 router-outlet 插入组件。 通常,一个好的候选对象可以标记一个 ViewContainer 应该被创建的位置,它是 ng-container 元素。它是作为一个注释呈现的,因此它不会向DOM引入冗余的html元素。下面是一个 ViewContainer 的示例:@Component({ selector: 'sample', template: ` <span>I am first span</span> <ng-container #vc></ng-container> <span>I am last span</span> ` })export class SampleComponent implements AfterViewInit { @ViewChild("vc", {read: ViewContainerRef}) vc: ViewContainerRef; ngAfterViewInit(): void { // outputs `template bindings={}` console.log(this.vc.element.nativeElement.textContent); } } 正如其他DOM抽象一样, ViewContainer 被绑定到通过 element 属性访问的特定DOM元素。在这个例子中,它绑定到 ng-container 元素作为注释,因此输出是 template bindings={} 。Manipulating views (操作视图) ViewContainer为操作视图提供了一个方便的apiclass ViewContainerRef { ...clear() : void insert(viewRef: ViewRef, index?: number) : ViewRef get(index: number) : ViewRef indexOf(viewRef: ViewRef) : number detach(index?: number) : ViewRef move(viewRef: ViewRef, currentIndex: number) : ViewRef } 我们前面已经看到了如何从模板和组件手动创建两种视图。一旦我们有了视图,我们就可以使用insert方法将它 insert 到DOM中。 ViewContainer还提供了自动创建视图的APIclass ViewContainerRef { element: ElementRef length: number createComponent(componentFactory...): ComponentRef<C> createEmbeddedView(templateRef...): EmbeddedViewRef<C> ... }下面是自动创建视图的例子import { Component, ViewChild, ComponentFactoryResolver, Input, ComponentRef, OnInit, AfterViewInit } from "@angular/core"; @Component({ selector: 'modal-host', templateUrl: './modal-host.component.html', styleUrls: ['./modal-host.component.scss'] }) export class ModalHostComponent{ isShow: boolean = false; @ViewChild('container') modalContentHost: ViewContainerRef; constructor( private componentFactoryResolver: ComponentFactoryResolver, ) { } private _contentComponent: any; @Input('content-data') contentData: any; @Input('content-component') set contentComponent(value: any) { this._contentComponent = value; if (!!this._contentComponent) { this.loadComponent(); } else { this.clearComponent(); } } get contentComponent() { return this._contentComponent; } private componentRef: ComponentRef<any>; loadComponent() { setTimeout(()=>{ this.isShow = true; },10) let componentFactory = this.componentFactoryResolver.resolveComponentFactory(this._contentComponent); this.modalContentHost.viewContainerRef.clear(); this.componentRef = this.modalContentHost.viewContainerRef.createComponent(componentFactory); if (!!this.contentData) { this.componentRef.instance.data = this.contentData; } } clearComponent() { if (!!this.modalContentHost) { this.modalContentHost.viewContainerRef.clear(); } this.isShow = false; } close() { } stopPropagation($event) { $event.stopPropagation(); } }ngComponentOutlet该指令类似于 ngTemplateOutlet,其不同之处在于它创建了一个宿主视图(实例化一个组件),而不是一个嵌入式视图,该指令在angular4+中开始出现。你可以这样使用:<ng-container *ngComponentOutlet="ColorComponent"></ng-container>
angular2以上视频播放结束方法
播放视频后需要触发某个事件,js的方法为监听ended事件:html:<video id="media" controls width="400px" heigt="400px"> <source src="src" > </video>js: var md=document.getElementsByTagName("video")[0]; md.addEventListener("ended",function(){ alert("播放结束"); })在angular中它提供了一个方法在视频播放结束后触发某个事件angular1中事件为on-ended,angular2以上为(ended);代码:template:<video (ended)="videoEnd()"> <source src="assets/vid.mp4" type="video/mp4"> </video>component:videoEnd() {}
ionic的APP启动时短暂的黑屏解决方法
在我们创建完一个ionic项目后,打包android安装之后启动的时候,从你开始点击APP启动到启动图出现的这个时间间隔的时间内屏幕处于黑屏状态,这是由于android初始化解析界面需要一定的时间。对于该问题处理方式也简单, 1.自定义theme:首先在该路径:project\platforms\android\res\values添加一个style.xml文件<resources><style name="Theme.AppStartLoadTranslucent" parent="android:Theme"><item name="android:windowIsTranslucent">true</item><!-- <item name="android:windowBackground">@drawable/screen</item> --><item name="android:windowNoTitle">true</item></style></resources>这个方法是把样式设置为透明,程序启动后就不会是黑屏的而是透明的了,等到程序初始化完成后一次性显示出来,这个方法的缺点是给人启动慢的感觉,但是程序是一次性刷出来,刷新同步了 2.修改androidmainfest.xml为了使第一步的代码生效,我们需要设置activity的theme <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:theme="@style/Theme.AppStartLoadTranslucent" android:windowSoftInputMode="adjustResize">红色标注的地方为改变之后的值; 通过设置这两个地方就能解决我们的APP启动的黑屏问题了,不过需要注意的是移除android的时候会将我们的修改删除,所以移除android平台之后再次添加的时候需要我们重新去配置