发布Angular应用至生产环境的方法


Posted in Javascript onDecember 10, 2018

两年前, 写过一篇使用rollup 来 为生产环境编译 Angular 2 应用 的文章, 因为当时还没有 angular-cli 项目。 而如今 Angular 已经到了 7.x 版本, 对应的工具也是非常的完善, 也就不在使用 rollup 来处理 angular 项目。

angular-cli 用起来虽然方便, 但是针对生产环境编译的话, 还是有一些地方要注意的, 接下来就介绍我在项目部署时的一些做法。

合理拆分功能模块, 按需加载

一个系统往往功能非常多, 因此就要根据项目的实际情况划分功能模块,一个功能模块对应一个 NgModule , 编译成一个独立的 js 文件, 再结合 angular 的路由技术进行按需加载,就这一功能点来说, angular 的支持已经非常的完善了。

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: './home/home.module#HomeModule' },
  { path: 'about', loadChildren: './about/about.module#AboutModule' },
  {
    path: 'arcgis',
    loadChildren: './arcgis/arcgis.module#ArcgisModule',
    canLoad: [EsriLoaderGuard]
  }
];

这一点经常容易被忽视, 曾经就出现过犹豫没有合理划分模块, 导致编译出来的 js 文件高达 5 兆, 造成的客户体验非常差。 (甚至还出现开发机内存不足,无法成功编译的情况)

预先压缩 js 文件

当然, 仅仅考合理划分 js 模块的话, 还往往不太够, 因为单个模块也可能会比较大, 可能会超过 1 兆, 特别是使用了一些第三方控件(ng-bootstrap, ng-zorro 等)的情况下。

针对这种情况, 通常还需要对编译生成的 js 文件进行 gzip 压缩, 因此在执行 ng build --prod 编译之后, 再继续执行下面的 shell 命令:

find dist -name "*.js" -print0 | xargs -0 gzip -k

当然, 如果发现编译生成 css 文件比较大的话, 也可以通过下面的命令进行压缩:

find dist -name "*.css" -print0 | xargs -0 gzip -k

以一个仅仅使用了 ng-bootstrap 的模板项目为例, 生成的 js 文件如下所示:

1.8K dist/ng-seed/4.1495aba38157395f4a2d.js
 1.7K dist/ng-seed/5.ec7eb27ea7c8eee53bcc.js
 482K dist/ng-seed/main.6ee651175769ea64ed5f.js
 37K dist/ng-seed/polyfills.5d61d41949cb87471fa8.js
 2.2K dist/ng-seed/runtime.c66e13242c809a55bd2f.js

其中的 main.6ee651175769ea64ed5f.js 就有 482KB , 而经过 gzip 压缩之后, 文件大小显著减小:

1.8K dist/ng-seed/4.1495aba38157395f4a2d.js
1.0K dist/ng-seed/4.1495aba38157395f4a2d.js.gz
1.7K dist/ng-seed/5.ec7eb27ea7c8eee53bcc.js
888B dist/ng-seed/5.ec7eb27ea7c8eee53bcc.js.gz
482K dist/ng-seed/main.6ee651175769ea64ed5f.js
124K dist/ng-seed/main.6ee651175769ea64ed5f.js.gz
 37K dist/ng-seed/polyfills.5d61d41949cb87471fa8.js
 12K dist/ng-seed/polyfills.5d61d41949cb87471fa8.js.gz
2.2K dist/ng-seed/runtime.c66e13242c809a55bd2f.js
1.2K dist/ng-seed/runtime.c66e13242c809a55bd2f.js.gz

main.6ee651175769ea64ed5f.js.gz 有 124KB , 只有原来的 1/4 。

一般来说, 对于 angular 项目编译出的 js 文件, gzip 压缩能减少 3/4 甚至 4/5 的体积, 这样将会显著减轻网络传输的压力。

使用 nginx 作为服务器

为什么使用 nginx 作为前端服务器呢? 原因如下:

支持传输预先压缩的 js 文件

将预先压缩好的 .js.gz 和原来的 .js 文件一起上传到服务器, 只要在 nginx 服务器的配置文件上加一句 gzip_static on; 即可启用,这样在客户端请求 .js 文件时, nginx 会先检查一下是否存在对应的 .js.gz 文件, 如果存在的话, 就直接返回 .js.gz 文件的内容, 从而省去了在服务端进行压缩的过程, 节省服务器的资源。

location /ng-app {
  root  /usr/share/nginx/html;
  index index.html index.htm;
  gzip_static on;
  try_files $uri /ng-app/index.html;
}

作为后台接口的网关

nginx 支持反向代理, 可以作为后台接口的网关, 这样可以省去一些跨域调用 (cors) 的问题, 一般的反向代理配置如下:

location /api {
  proxy_pass http://api-server:8080/api;
  proxy_read_timeout 600s;
  proxy_redirect off;
  proxy_set_header Host $host;
  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;
}

官方的 docker 镜像

nginx 有 docker 的官方镜像, 部署、升级都是非常的方便。 不得不说docker 确实是好东西, 用了就停不下来了。

这几点都是在项目中积累的一些小技巧, 如果想要了解细节, 请查看这个ng-seed 项目。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery onload、ready概念介绍及使用方法
Apr 27 Javascript
事件委托与阻止冒泡阻止其父元素事件触发
Sep 02 Javascript
JavaScript获取网页中第一个图片id的方法
Apr 03 Javascript
js实现仿网易点击弹出提示同时背景变暗效果
Aug 13 Javascript
KnockoutJS 3.X API 第四章之数据控制流foreach绑定
Oct 10 Javascript
JavaScript中访问id对象 属性的方式访问属性(实例代码)
Oct 28 Javascript
Angular4项目中添加i18n国际化插件ngx-translate的步骤详解
Jul 02 Javascript
ES6中字符串string常用的新增方法小结
Nov 07 Javascript
在vue项目中安装使用Mint-UI的方法
Dec 27 Javascript
element-ui表格列金额显示两位小数的方法
Aug 24 Javascript
使用puppeteer爬取网站并抓出404无效链接
Dec 20 Javascript
JS判断浏览器类型与操作系统的方法分析
Apr 30 Javascript
webpack优化的深入理解
Dec 10 #Javascript
BootStrap模态框闪退问题实例代码详解
Dec 10 #Javascript
详解为生产环境编译Angular2应用的方法
Dec 10 #Javascript
深入理解Vue.js轻量高效的前端组件化方案
Dec 10 #Javascript
es6基础学习之解构赋值
Dec 10 #Javascript
vue中将html字符串转换成html后遇到的问题小结
Dec 10 #Javascript
vue的.vue文件是怎么run起来的(vue-loader)
Dec 10 #Javascript
You might like
PHP生成HTML静态页面实例代码
2008/08/31 PHP
php微信公众开发之获取周边酒店信息的方法
2014/12/22 PHP
PHP获取数组长度或某个值出现次数的方法
2015/02/11 PHP
tp5(thinkPHP5)操作mongoDB数据库的方法
2018/01/20 PHP
利用PHP内置SERVER开启web服务(本地开发使用)
2021/03/09 PHP
javascript 动态添加事件代码
2008/11/30 Javascript
JS判断两个时间大小的示例代码
2014/01/28 Javascript
Jquery 实现table样式的设定
2015/01/28 Javascript
45个JavaScript编程注意事项、技巧大全
2015/02/11 Javascript
Jquery动态添加输入框的方法
2015/05/29 Javascript
教你如何终止JQUERY的$.AJAX请求
2016/02/23 Javascript
AngularJs  unit-testing(单元测试)详解
2016/09/02 Javascript
vue实现添加标签demo示例代码
2017/01/21 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
2017/09/11 Javascript
详解Node全局变量global模块
2017/09/28 Javascript
python使用pil生成图片验证码的方法
2015/05/08 Python
python设定并获取socket超时时间的方法
2019/01/12 Python
详解django+django-celery+celery的整合实战
2019/03/19 Python
python rsync服务器之间文件夹同步脚本
2019/08/29 Python
python序列类型种类详解
2020/02/26 Python
Keras 加载已经训练好的模型进行预测操作
2020/06/17 Python
tensorflow 2.0模式下训练的模型转成 tf1.x 版本的pb模型实例
2020/06/22 Python
python 两种方法删除空文件夹
2020/09/29 Python
html如何对span设置宽度
2019/10/30 HTML / CSS
C#如何调用Windows程序打开一个文档
2014/12/26 面试题
实习生的自我鉴定范文欣赏
2013/11/20 职场文书
写给女朋友的道歉信
2014/01/12 职场文书
高一英语教学反思
2014/01/22 职场文书
演讲主持词
2014/03/18 职场文书
售后服务承诺书怎么写
2014/05/21 职场文书
护士个人总结范文
2015/02/13 职场文书
工会文体活动总结
2015/05/07 职场文书
红白喜事主持词
2015/07/06 职场文书
初任公务员培训心得体会
2016/01/08 职场文书
MySQL之高可用集群部署及故障切换实现
2021/04/22 MySQL
VW、VH适配移动端的解决方案与常见问题
2023/05/21 HTML / CSS