日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

總結

以上是生活随笔為你收集整理的angular设置referer_Angular-cli 构建应用的一些配置的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。