之前的开发选择的是完全舍弃服务端,仅保留最简单 web 服务器提供 angular 经打包的静态资源,此外所有的业务与数据请求都访问一个分离的 WebApi 来实现。不过最近碰到一个需求,有必要使用多个客户端,而各客户端本身都是 webpack 打包出来的 js 而已,没必要每个客户端都自己建一个站点,这就有必要搭建一个服务端,根据参数动态渲染不同客户端的脚本来服务多个客户端了。主要需要解决两个问题,一是防止前后端路由冲突各自有效工作,二是如何实现一套比较合理的部署方案。笼统一点看待这个问题,无非就是要实现如题目所描述的,如何将专注前端的强大框架 (angular) 整合到一个健壮的现有服务端 (.Net) 项目中去。
第一步必然是要先得到前端项目的打包资源,由强大的 webpack 来完成,目标是将 angular 的所有依赖以及应用主代码分别打包到 polyfill.js、vendor.js、main.js 三个脚本中,以及异步懒加载的模块各自打包成一个 chunk.js。webpack 博大精深,刚接触会摸不着头脑,好在其终究是用来给我们带来方便的一个工具而已,使用起来是很有条理的。其主要的介绍可以移步 webpack 的官方文档【https://doc.webpack-china.org 】,认真吸收完远远足够写出 angular-webpack-starter【 https://github.com/AngularClass/angular-starter 】这样完善的启动项目来了。简单来说 webpack 配置有四部曲:
- entry: {
- 'polyfills': './src/polyfills.browser.ts',
- // 依赖项
- 'main': AOT ? './src/main.browser.aot.ts': './src/main.browser.ts' // 主程序
- },
打包规则有好一些需要配置的,包括了各种文件类型的打包,angular 模块的打包等,配置方式见官方文档或直接参照现成的启动项目,直接看难免懵逼,但不要怕,规则其实就那么点,眼熟就成功了大半。
webpack 有非常多的插件,用来强化打包能力以及规则的扩展,可以看看启动项目中用到了哪些,这些插件在官方文档里都能找到介绍。
输出要分生产环境和开发环境,本文只讲生产环境。先明确 webpack 打包好的项目是要交给服务端使用的,给出的输出要有几个需求: 1) 转义兼容浏览器和 ES5 并压缩。2) 输出文件名附带哈希值,代码发生更改重新打包时要有不同的哈希值,保证此时替换的资源不会被浏览器缓存而得不到第一时间更新。3) 列出资源打包清单,因为附带了哈希值导致每次文件名都是很长一串奇怪字符,使用合适的 webpack 配置附带一个 manifest 清单列出都输出了哪几个文件,进一步在使用时动态读取其中的清单来操作输出的文件。
顺利的话开发完成的项目能得到类似下图的打包资源:
其中 webpack-assets.json 中列出了三个依赖文件:
以 0、1、2、3 打头的四个 chunk 文件是由 angular 动态引入的懒加载模块,不需要手动引入自然也不需要列出来,只需要保证 angular 能访问到它们即可。把这些东西全都放到一个. Net MVC 项目中去:
然后在 View 视图中引入三个脚本并配置 base url:
现在运行 MVC 项目,定位到这个视图可以顺利渲染出 angular 项目来。问题在于手动输入前端路由的 url 时,此 url 会被 MVC 路由视为 404 错误 (因为 MVC 路由中确实未定义这一规则,真正使用此规则的 angular 客户端还没有机会解析这个 url 就被一个错误页取代了)。
angular 官方给出的指南是给服务端配置 404 的重定向,将所有的 404 错误都重定向到 index.html,这样前端就能顺利开始解析输入的 url 了。在 MVC 中做法也类似,只要在 MVC 的路由规则中,将必要路由 (比如还定义了其他的 Api 或者错误页) 之外的所有请求都指向指定的 Action,比如笔者的这条规则,将所有其他请求都指向 AppController 下的 Index:
这样除了 / page / 打头的 url 外所有不满足默认路由的请求都会定位到 / App/Index。
下一步是要在这个 / App/Index 中读取前端打包生成的 webpack-assets.json 清单,将需要的文件渲染到视图中,笔者项目添加了一个 academyid 来区分多客户端,每个客户端都有以自己 id 命名的一个资源目录,实现如下图所示:
笔者的 C# 比较抠脚,所以定义了一个 class 来解析 json 文件,然后才把解析到的文件名放到 ViewData 中以供前端使用。现在视图中就可以使用 Razer 语法来渲染脚本依赖:
这样子配置下来,服务端其实不需要再关心客户端的更改,只关心从 webpack-assets.json 中解析要加载的依赖,并渲染这些依赖即可,每当客户端代码更改重新打包时,webpack-assets.json 清单也会更新,毫不影响服务端。
水平有限导致本文存在许多的不足之处,包括一直未涉及的 SEO 方案以及其他的隐藏问题,笔者还有很多需要学习完善的地方。
来源: http://www.cnblogs.com/yitim/p/7085828.html