angular设置referer_Angular-cli 构建应用的一些配置

Angular-cli 构建应用

的一些配置

标签(空格分隔): Angular

直接使用 ng build --prod --build-optimizer --base-href=/ 来发布

base-href可以设置服务器上的某个子路径,使用 ng build --base-href=/my/path/

如果打包静态文件(js和css)不放在和index.html同一路径下,可以在.angular-cli.json配置文件apps属性下增加deployUrl,等同于webpack的publicPath。

如遇刷新找不到页面(404)的情况,需要在服务器配置重定向到index.html。以nginx为例,可以在location添加try_files $uri $uri/ /index.html?$query_string;来重定向到index.html。

如果碰到 *ngIf *ngFor用不了得情况,比如抛出 Property binding ngForOf not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations".的错误,通常是因为没有importCommonModule,而且这个import必须在组件被引用的module中。比如我把routes和modules分离,这样组件将会在xx-routing.module.ts中被import,那么这个CommonModule就得在xx-routing.module.ts中被import,在xx.module.ts引用是不行的。

首次项目实践问题记录

1. node版本升级(v6.x.x -> v8.11.1)后,原来项目ng serve抛出错误:Node Sass could not find a binding for your current environment。

此时需要执行npm rebuild node-sass来解决。参见stackoverflow。

2. 想要在整个应用初始化时候,在路由导航之前就请求数据,可以通过APP_INITIALIZER实现。

app.module.ts

export function loadToken(tokenService: InitDataService) {

return () => tokenService.tokenAndTime();

}

providers: [

...

{

provide: APP_INITIALIZER,

useFactory: loadToken,

deps: [InitDataService],

multi: true

},

...

],

*值得一提的是,目前只实现了同步数据获取,如果异步,并不能在路由渲染完毕之前获取完成。有待研究。 *

3. 关于querySelector()选择器,默认是返回Element,这时候就不能在其后用.style了。

需要将选择到的Element转为HTMLElement(参见):

let overlay = document.querySelector(`#${this.ID}`);

overlay.style.display = 'none';

4. 关于angualr的HttpClient,post请求默认将body中的数据序列化为json,如果后台只接收urlencoded格式的数据,就不能直接传对象了:

private init() {

this.url = apiData.ServiceUrl + this.path;

const datas: Datas = {

ClientType: apiData.ClientType,

Token: this.tokenDatasService.token

};

Object.assign(datas, this._datas);

// 将参数对象序列化为 [key1]=[value1]&[key2]=[value2]的字符串

let params = new HttpParams();

if (!this.isGet) {

datas.Timespan = this.tokenDatasService.timespanFormat;

}

for (let key in datas) {

params = params.set(key, datas[key]);

}

if (this.isGet) {

this.datas = { params: params };

} else {

this.datas = params;

}

}

5. 如果想要使组件样式可以应用到子组件,可以通过

@Component({

encapsulation: ViewEncapsulation.None,

...

})

这时样式将不再局限于当前组件。

6. 如果想要当前根路径(子根路径)导航到未匹配路由时,比如设置404,可以在路由数组的末尾添加

const ROUTES: Routes = [

...

{ path: '**', component: NotFoundComponent}

];

7. 关于polyfills.ts

之前没有取消注释这个文件中的引用,在IE下打开发现报错,取消注释第一块引用后,发现所有浏览器都出现自定义DI抛出错误Uncaught Error: Can't resolve all parameters for ApiService: (?). at syntaxError (compiler.es5.js:1694) ...。

google了半天都是说没写@Injectable()或者少@或者(),然而检查了半天并不是。最后在GitHub的一个Issues中找到了答案,需要取消注释import 'core-js/es7/reflect';即可解决。原因暂且未去探究。

8. 关于再ng中使用canvas

使用@ViewChild('[name]') canvasRef: ElementRef来选择canvas画布。

9. 关于资源路径,使用绝对路径,比如css中获取logo图片:

background: url("/assets/img/shared/logo.png") no-repeat center/100%;

10. 父子路由可以通过

父级提供服务支持(providers),父级在constructor方法中订阅(subscribe),子路由在ngOnInit方法或者其他自定义事件中赋值(next)。

11. 通过方括号绑定的routerLink属性,值是异步获取的(Observable)。这时候subscribe的时候抛出 ExpressionChangedAfterItHasBeenCheckedError 。

可以通过setTimeout([callback], 0)异步处理结果实现参见GitHub Issues:

this.accountService.titles$.subscribe(titles => setTimeout(() => {

this.title = titles.title;

this.titleLink = titles.titleLink.link;

this.titleLinkName = titles.titleLink.name;

}, 0));

12. 在开发环境(ng serve)中,各个路由刷新页面正常显示,但是打包部署到服务器后,在子路由中刷新页面会出现404。可以通过配置服务器来修复这一问题:

以nginx为例:

location / {

root C:\Web\Site;

index index.html;

ry_files $uri $uri/ /index.html?$query_string;

}

13. vue中习惯使用v-if和v-else,ng中也有这样的模板语法:

注意必须使用ng-template。

{{ userInfo.Name }}

立即登录

14. 使用Subject实现组件之间的通信

ionic中有一个Events服务,可以通过publish发布事件,在其他组件中subscribe事件。

在Angular项目中,我们可以通过Subject来创建一个服务实现类似的效果。类同本文(# 10)所述。

首先创建一个公共服务:

import {Injectable} from '@angular/core';

import {Datas} from '../models/datas.model';

import {Subject} from 'rxjs/Subject';

import {Observable} from 'rxjs/Observable';

import {Subscriber} from 'rxjs/Subscriber';

@Injectable()

export class EventsService {

private events: Datas = {};

public eventsName = [];

constructor() { }

/**

* 发布

* @param {string} topic 事件名称

* @param {Datas} params 参数(对象)

*/

public publish(topic: string, params: Datas = {}) {

const event = this.getEvent(topic);

Object.assign(params, { EVENT_TOPIC_NAME: topic });

event.next(params);

}

/**

* 订阅事件

* @param {string} topic 事件名称

* @return {Observable}

*/

public subscribe(topic: string) {

return this.getEvent(topic).asObservable();

}

/**

* 取消订阅事件

* @param {Subscriber} subscriber 订阅事件对象

*/

public unsubscribe(subscriber: Subscriber) {

subscriber.unsubscribe();

}

private getEvent(topic: string) {

this.eventsName.push(topic);

this.eventsName = Array.from(new Set(this.eventsName));

let _event;

for (const i in this.events) {

// 判断是否已有事件

if (this.events.hasOwnProperty(i) && i === topic) {

_event = this.events[i];

break;

}

}

if (!_event) {

// 没有事件 创建一个

_event = new Subject();

const eventObj = { [topic]: _event };

Object.assign(this.events, eventObj);

}

return _event;

}

}

然后在某组件中订阅事件

...

constructor(private eventsService: EventsService) { }

ngOnInit() {

const a = this.eventsService.subscribe('setHeader').subscribe(v => {

console.log(v);

// 取消订阅

this.eventsService.unsubscribe(a);

});

}

...

在某组件中发布事件(触发或许更为贴切)

...

export class IndexComponent implements OnInit {

constructor(private eventsService: EventsService) { }

ngOnInit() {

// 第一次触发

this.eventsService.publish('setHeader', { a: 1, b: 2 });

setTimeout(() => {

// 第二次触发

this.eventsService.publish('setHeader', { c: 3 });

}, 5000);

}

}

在控制台,我们可以看到:

第二次触发并没有被打印。是因为调用了取消订阅事件。将取消订阅事件注释掉,可以看到第二次触发打印:

15. 监听路由跳转

经常会用到路由跳转后执行一些操作。通过

import {NavigationEnd, Router} from '@angular/router';

...

constructor(private router: Router) { }

...

// 导航

navWatch() {

this.router.events.subscribe(e => {

if (e instanceof NavigationEnd) {

// TODO 路由跳转完毕

}

});

}

...

16. 为组件添加事件

使用@Output() [eventName] = new EventEmitter();,然后在组件内部通过this[eventName].emit([params])来触发事件、传递参数。组件外部通过圆括号。其中$event就是传递过来的参数。

17. 监听宿主事件

比如监听window滚动事件:

...

@HostListener('window:scroll', [])

onWindowScroll() {

// TODO 滚动事件

// this.scrollEvent().subscribe(obj => {

// this.scrollStyle(obj.offset, obj.direction);

// });

}

...

18. 自定义表单验证器

如何实现两次输入密码一致(两个输入框值相等)的自定义验证器。

19. 给元素绑定data-*等属性

直接使用方括号你会发现抛出错误。这时候可以加个attr来解决:

20. 关于css3 rem的使用

我们习惯使用 html { font-size: 62.5%; }来作为根大小(10px),但是Chrome并不支持12px以下的大小,这将导致Chrome与其他浏览器显示不同。

搜索解决方案。

设置body { font-size: 1.4em; },经试验不起作用(至少在我的项目中)。

使用-webkit-transform: scale(.8, .8);,不是很满意。

使用html { font-size: 625%; },相当于100px。

我更偏向于第三种。

如果想要手动配置webpack来打包项目:(非必要)

使用ng new my-app初始化的项目并不包含webpack配置文件,需要ng eject命令来加入webpack.config.js配置文件。

注意此时不能再用 ng build 之类的命令了,开发环境是npm start,打包命令是npm run build。

这时候webpack缺少一些原来的配置。

1. uglifyjs-webpack-plugin js压缩插件

将js文件压缩,减小打包后文件的体积。

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

...

new UglifyJsPlugin({

"test": /\.js$/i,

"extractComments": false,

"sourceMap": true,

"cache": false,

"parallel": false,

"uglifyOptions": {

"output": {

"ascii_only": true,

"comments": false

},

"ecma": 5,

"warnings": false,

"ie8": false,

"mangle": {

properties: {

regex: /^my_[^_]{1}/,

reserved: ["$", "_"]

}

},

"compress": {}

}

})

2. compression-webpack-plugin 生成gzip文件插件

进一步减小打包文件体积。

const CompressionWebpackPlugin = require('compression-webpack-plugin');

...

new CompressionWebpackPlugin()

这个需要服务器开启gzip on;,以nginx为例,需要为服务器进行以下配置:

conf/nginx.conf:

http {

include mime.types;

default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '

# '$status $body_bytes_sent "$http_referer" '

# '"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;

#tcp_nopush on;

#keepalive_timeout 0;

keepalive_timeout 65;

# 开启gzip

gzip on;

gzip_static on;

gzip_min_length 1k;

gzip_buffers 4 16k;

gzip_comp_level 2;

gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

gzip_vary on;

gzip_disable "MSIE [1-6]\.";

server {

listen 8088;

server_name localhost;

location / {

root website/angular;

index index.html;

}

}

}

3. clean-webpack-plugin 清除打包文件工具

每次npm run build后都会生成新的打包文件(文件名添加hash),这个插件可以在打包后删除之前旧的文件。

const CleanWebpackPlugin = require('clean-webpack-plugin');

...

new CleanWebpackPlugin(['dist'], {

root: projectRoot,

verbose: true,

dry: false

})

4. CopyWebpackPlugin 配置修改

src/assets/文件夹下的静态资源以及favicon.ico文件也需要打包,这时需要修改一下自动生成的配置代码:

new CopyWebpackPlugin([

{

"context": "src",

"to": "assets/",

"from": "assets"

},

{

"context": "src",

"to": "",

"from": {

"glob": "favicon.ico",

"dot": true

}

}

], {

"ignore": [

".gitkeep",

"**/.DS_Store",

"**/Thumbs.db"

],

"debug": "warning"

}),

5. Extract Text Plugin 的使用(存在问题)

如果需要分离css单独打包,可以使用 extract-text-webpack-plugin 。

可能会有解决方案,暂时不做深入探究。还是推荐直接使用ng-cli。

注意,分离css后,angular的特殊选择器将失效,比如:host {}选择器,使用正常的css方法实现来替代。

注意,样式的引用就需要通过import './xx.scss';的方式来引用样式文件,否则会抛出Expected 'styles' to be an array of strings.的错误。

也有通过"use": ['to-string-loader'].concat(ExtractTextPlugin.extract())的方法来实现。

因为不通过@Component({ styleUrls: '' })的方式,样式的scope作用将消失。

webpack.config.js:

const ExtractTextPlugin = require('extract-text-webpack-plugin');

const extractCSS = new ExtractTextPlugin('[name].[contenthash:8].css');

const extractSCSS = new ExtractTextPlugin('[name].[contenthash:8].css');

module.exports = {

...

"entry": {

...

"styles": [

"./src/app.scss"

]

},

"module": {

"rules": [

{

"test": /\.css$/,

"use": extractCSS.extract({

"fallback": "style-loader",

"use": [

{

"loader": "css-loader",

"options": {

"sourceMap": false,

"import": false

}

},

{

"loader": "postcss-loader",

"options": {

"ident": "postcss",

"plugins": postcssPlugins,

"sourceMap": false

}

}]

})

},

{

"test": /\.scss$|\.sass$/,

"use": extractSCSS.extract({

"fallback": "style-loader",

"use": [

{

"loader": "css-loader",

"options": {

"sourceMap": false,

"import": false

}

},

{

"loader": "postcss-loader",

"options": {

"ident": "postcss",

"plugins": postcssPlugins,

"sourceMap": false

}

},

{

"loader": "sass-loader",

"options": {

"sourceMap": false,

"precision": 8,

"includePaths": []

}

}]

})

},

],

"plugins": [

...

extractCSS,

extractSCSS

]

}

...

}

app.component.ts

import './app.component.scss';

@Component({

selector: 'app-root',

templateUrl: './app.component.html'

})

6. publicPath

webpack 有一个publicPath 属性,可以设置资源引用路径,需要写在output属性下:

module.exports = {

...

"output": {

"publicPath": '/',

"path": path.join(process.cwd(), "dist"),

"filename": "[name].bundle.[chunkhash:8].js",

"chunkFilename": "[id].chunk.[chunkhash:8].js",

"crossOriginLoading": false

},

...

}

如果使用ng-cli,可以在apps属性下设置deployUrl,等同于publicPath。

我的环境

Angular CLI: 1.6.7 (e)

Node: 8.11.1

OS: win32 x64

Angular: 5.2.3

The end... Last updated by: Jehorn, Sep 17, 2018, 04:29 PM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式(三)创建型模式

前言 根据菜鸟教程的目录,我们首先来看看创建型模式。 创建型模式研究: 实际应用中通常有哪些不同的创建对象的场景;在不同的场景下,如何更好地编写创建对象的代码。主要研究构造函数。 下面分别对创建型模式下的各种具体模式进…

CSDN改版,找不到各种入口,链接放下面

https://mp.csdn.net/console/article?spm1010.2135.3001.5128 https://mp.csdn.net/console/column/allColumnList 分类管理 https://mp.csdn.net/console/article 文章管理 https://mp.csdn.net/console/upDetailed 资源管理 https://mp.csdn.net/editor/html?spm1011.…

python中pca算法_python实现PCA算法01

python实现PCA算法Software version: Python 2.7.12 |Anaconda 4.2.0 (64-bit)|法1. 编程一步一步实现法2. sklearn我们以定义函数的形式来一步一步进行1.1 导入模块:Numpy,Pandas# -*- coding: utf-8 -*-# Time : 2017/8/17 14:20# Author :…

设计模式(一)预备知识

前言 学习设计模式需要有面向对象编程的基础,要基本掌握一种面向对象的编程语言。关于面向对象编程思想,我们有另外一篇文章专门讲解:面向过程和面向对象的联系和区别。 知识点 虚函数 在类的成员函数定义中,形式上为定义为vir…

【转】GitHub 从单机到联机:玩转 Pull Request

最近在参与一个叫 Exercism 的项目,这是一个由 GitHub 生态工程师 Katrina Owen 发起的编程练习社区,提供了超过50门语言的练习。作为用户,你仅需使用命令行工具即可下载和提交练习,提交后还可以和社区中其他学习者交流讨论。 Exe…

android cmake 打印_Android使用CMAKE编译libjpeg

本文主要介绍使用 CMAKE 编译 libjpeg-turbo 类库,本文相关代码请在GitHub-TurboJpegSample 查看。libjpeg-turbo 附GitHub 地址,libjpeg-turbo 是个运用极其广泛的库,可以说,基本上电脑上手机上能见到的 JPEG 压缩的地方用的一般…

设计模式(四)结构型模式

前言 结构型设计模式,主要研究: 主要有哪些场景使用结构型设计模式;每种场景应该使用何种设计模式;以程序中的功能为核心,研究程序功能的组织结构。所以这一章,我们要把“功能结构”作为研究的核心。 下…

centos 删除crontab_centos下crontab的使用

4.cron文件语法:分 小时 日 月 星期 命令0-59 0-23 1-31 1-12 0-6 command (取值范围,0表示周日一般一行对应一个任务)5.记住几个特殊符号的含义:“*”代表取值范围内的数字,“/”代表”每”,“-”代表从某个数字到某个数字,“,”分开…

【转】GitHub客户端操作1--仓库相关操作github团队协作流程

1、创建仓库 点击“”,点击Create,然后填写Name为my,点击Create repository,即可创建一个my仓库 2、从本地仓库存放位置,添加test仓库到GitHub客户端 点击“”,点击Add,然后点击Browse,选择仓库存放位置&a…

音视频相关链接

开发库 FFmpeg FFmpeg官网 FFmpeg github 平台相关 DirectShow DirectShow简介 DirectShow官网

【转】GitHub客户端操作2--分支操作

简单分支操作 (1)创建新分支:my分支 备注:新创建的分支:my分支里面的内容是和master分支里面的内容是完全一样的。 (2)删除my分支 (3)修改my分支【在my分支上进行项目内…

uniapp动态修改样式_uniapp样式动态绑定

场景一:用户点击按钮后动态切换按钮选中样式(如图)已上线未开始//选择状态selectState(e){this.whichSelectede.currentTarget.dataset.state}.state-btn-content{//write your style.state-btn-selected{ ... }.state-btn-noselect{ ... }}注:需要注意的…

音视频工程师(初步)(一)音视频的基本概念

1. 前言 本文是音视频工程师系列的第一篇文章。 学习音视频的过程中发现,网络上高质量的音视频技术博客不是很多。具有代表性的是 雷神的 雷霄骅的CSDN博客 因为笔者是一名普通的软件开发人员,一向不喜欢高高在上或者晦涩难懂的理论,我们…

【转】GitHub客户端操作3--pull Request(拉请求)

一、参考说明 参考文章一:Github上提交代码(pullrequest) 网址: https://jingyan.baidu.com/article/358570f64dcdc2ce4724fc32.html 参考文章二:GitHub——Pull Request 网址:http://blog.csdn.net/u012325167/article/detai…

webstorm 内存溢出怎么弄_webstrom 内存溢出,软件崩溃卡死解决的方法

今天用gulp搭建了一个工程,准备做一个体育h5的项目,其中需要用到sass代码压缩,加版本号等功能.gulpfile.js和package.json都是已经写好的.我用CMD命令窗口cnpm安装node_modules依赖文件.当我安装完毕之后用webstrom打开时,第一件事先把node_modules排除忽略了.如下:然后我去编辑…

躺平也要看,2022年计算机相关考试汇总

1. 全国计算机专业资格考试(软考) 1.1 官网 全国官网:https://www.ruankao.org.cn/,从全国官网首页的底部可以直达各个省区的考试机构报名网站。 1.2 考试安排 软考一年两次。 场次报名时间考试时间上半年 预计报名时间在2月…

【转】GitHub上README.md教程

本文是转载文章,文章的来源:csdn博客 博主:果冻虾仁 文章: GitHub上README写法暨GFM语法解读 博文地址:https://blog.csdn.net/guodongxiaren/article/details/23690801 转载请保留原作者guodongxiaren的原文地址&…

python supervisor flask_supervisor配合uwsgi部署flask应用

这已经是第N次来部署flask应用了, 但是每次都花了不少时间在配置上面, 这里一次性记录下, 备个忘~写在前面其实使用uwsgi来部署flask应用在官网上已经有较为详细的 文档 了, 推荐先读一下.先解决一些问题:为何使用 uwsgi 来部署应用? 方便管理; 较为常见的部署方式; 可配置性较…

设计模式(五)行为型模式

前言 在上一篇结构型模式中,我们以功能为基本单位,研究了一些设计模式,用于实现功能转换、功能组合、功能封装等目的。 我们知道,面向对象编程有两个核心元素:对象、对象间通信协作。从面向对象的角度看,…

51单片机auxr寄存器_51—52系列单片机特殊功能寄存器一览表

P2.1P2.0RSTP3.0/RXDP3.1/TXDXTAL2XTAL1P3.2/INT0P3.3/INT1P3.4/T0P3.5/T1GNDVCCP1.7P1.6P1.5P1.4P1.3P1.2P1.1/AIN1P1.0/AIN0P3.7注:类似的还有Philips公司的87LPC64,20引脚8XC748/750/(751),24引脚8X749(752),28引脚8XC754&…