Leo*_*chi 9 asp.net-mvc webpack angular
我正在寻找一个可以遵循的步骤,将Angular添加到现有的MVC应用程序中,该应用程序位于我的解决方案区域.我找到了一个编写,告诉我如何使用gulp.js文件添加角度,该文件提取必要的node_modules并将我的ts文件转换为js文件.我想用webpack做同样的事情.
目前我的package.json看起来像这样.
{
"version": "1.0.0",
"name": "aspnet",
"private": true,
"scripts": {},
"dependencies": {
"@angular/animations": "4.3.5",
"@angular/common": "4.3.5",
"@angular/compiler": "4.3.5",
"@angular/compiler-cli": "4.3.5",
"@angular/core": "4.3.5",
"@angular/forms": "4.3.5",
"@angular/http": "4.3.5",
"@angular/platform-browser": "4.3.5",
"@angular/platform-browser-dynamic": "4.3.5",
"@angular/platform-server": "4.3.5",
"@angular/router": "4.3.5",
"@angular/upgrade": "4.3.5",
"angular-in-memory-web-api": "0.3.2",
"bootstrap": "3.3.7",
"core-js": "2.5.0",
"ie-shim": "0.1.0",
"rxjs": "5.4.3",
"zone.js": "0.8.16",
"systemjs": "^0.20.18"
},
"devDependencies": {
"gulp": "^3.9.1",
"gulp-clean": "^0.3.2",
"gulp-concat": "^2.6.1",
"gulp-tsc": "~1.3.2",
"gulp-typescript": "^3.2.2",
"path": "^0.12.7",
"typescript": "^2.4.2"
}
}
Run Code Online (Sandbox Code Playgroud)
这是我遵循的写作,使用gulp,这是有效的.
但我更愿意使用webpack而不是gulp任务.
tru*_*k18 16
我希望这可以帮助您找到想法,因为我们的项目还需要将webpack和ASP.NET MVC集成在一起.注意到这是我自己的提议,所以可能有更好的方法来做到这一点.以下是我们的工作.
1.构建项目
我们将项目分为两个文件夹:Client和Server.这些文件夹将位于mvc5-angular-webpack文件夹中,此文件夹将提交到存储库
mvc5-angular-webpack/
??? Server/
? ??? WebApplication/
? ? ??? Controllers/
? ? ??? Scripts/
? ? ??? Web.config
? ? ??? Many more folder and file...
? ?
? ??? Web-Core.sln
?
??? Client/
??? modules
? ??? angularModule-1/
? ? ??? main.ts
? ? ??? app.modules.ts
? ? ??? app.component.ts
? ? ??? Many more file...
? ?
? ??? angularModule-2/
? ? ??? main.ts
? ? ??? app.modules.ts
? ? ??? app.component.ts
? ? ??? Many more file...
? ??? polyfill.ts
? ??? vendor.ts
?
??? build.bat
??? npm-shrinkwrap.json
??? package.json
??? tsconfig.json
??? tslint.json
??? webpack.config.js
Run Code Online (Sandbox Code Playgroud)
Web-Core.sln
,所有公共库项目都是用C#编写的.build.bat
.我稍后会讨论这个文件内容.在modules模块文件夹中,我们的项目将为每个模块创建每个子文件夹.我们的网站有一些模块仍在使用纯Razor的服务器端渲染.并且有一些用AngularJS和Angular在客户端代码中编写的模块.
2.配置 webpack
假设您已经配置了所有typescript
和npm
已经.让我们看看里面有什么webpack.config.js
const webpack = require('webpack')
const path = require('path')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const entryPath = path.resolve(__dirname, 'modules')
const corePath = path.resolve(__dirname, '../Server/WebApplication/Scripts/ng2')
const module1 = `${entryPath}/angularModule-1`
const module2 = `${entryPath}/angularModule-2`
module.exports = (envOptions) => {
envOptions = envOptions || {};
const config = {
entry: {
'polyfills': `${entryPath}/polyfill.ts`,
'vendors': `${entryPath}/vendor.ts`,
'module1': `${module1}/main.ts`,
'module2': `${module2}/main.ts`
},
output: {
path: corePath,
filename: '[name].js',
sourceMapFilename: "[name].js.map"
},
resolve: {
extensions: ['.ts', '.js', '.html']
},
module: {
rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'raw-loader'
},
{
test: /\.css$/,
loader: 'raw-loader'
}
]
},
devtool: 'source-map',
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: ['vendors', 'polyfills']
})
]
}
if (envOptions.MODE === 'prod') {
config.plugins.push(
new UglifyJsPlugin()
)
}
return config;
}
Run Code Online (Sandbox Code Playgroud)
所以基本上它会尝试解析上层的目录,并将所有编译的文件放在Server文件夹中的Scripts/ng2中.
3.配置npm脚本
配置完成后webpack
,我们基本上会在构建过程中添加一些脚本来运行.将以下代码添加到package.json
文件中
"scripts": {
"tsc": "tsc",
"tsc:w": "tsc -w",
"dev": "webpack-dev-server --https --open",
"watch": "webpack --config webpack.config.js --watch",
"build": "webpack --config webpack.config.js",
"build:html": "webpack --config webpack-html-plugin.config.js --env.MODE=prod",
"build:prod": "webpack --config webpack.config.js --env.MODE=prod"
}
Run Code Online (Sandbox Code Playgroud)
4.配置 build.bat
在Angular 2集成开始时,我们创建了一个用于前端目的的空Web应用程序项目,并将此项目添加为我们的依赖项WebApplication
.但我们的后端团队后来抱怨前端流程的速度有多慢.因为每次构建时都不需要构建前端项目WebApplication
.
该build.bat
文件的想法是手动运行它以在其机器上获得最新版本的前端代码.不是每次他们都运行项目.
call npm install --production --loglevel verbose
echo "Build Angular projects"
npm run build:prod
Run Code Online (Sandbox Code Playgroud)
该call
是继续,因为一些命令中止命令行.请参考这里
这里的脚本非常简单.首先,我们运行npm install来恢复所有必要的依赖项.然后build:prod
按我们package.json
之前的定义调用.Webpack将把我们的Typescript代码捆绑成三个大的JavaScript文件vendors.js
,polyfills.js
和module1.js
.
我们的团队使用Jenkins进行部署,所以我们的开发人员只需要包含运行build.bat
,我们都已经完成了.如果要在每次构建项目时运行它,可以在预构建或后构建事件中进行设置.
5.在视图中引用已编译的JavaScript文件.
通常我们只返回一个区域中的一个视图,如下所示.这my-angular-app
就是我们所定义的app.component.ts
Index.cshtml
<script src="~/Scripts/ng2/polyfills.js"></script>
<script src="~/Scripts/ng2/vendors.js"></script>
<script src="~/Scripts/ng2/module1.js"></script>
<my-angular-app>
Loading...
</my-angular-app>
Run Code Online (Sandbox Code Playgroud)
HomeController.cs
public ActionResult Module1()
{
return View();
}
Run Code Online (Sandbox Code Playgroud)
如果我们部署到生产,这有点缺点.因为在编译的JavaScript更新之后,浏览器有时会因为缓存而保留旧版本的文件.我们应该有一种机制来在部署后为文件提供唯一的名称.我们有3种选择.
如果我们使用纯前端项目,请webpack
提供html-webpack-plugin来处理它,如下所示.从技术上讲,它会使用唯一ID自动将JavaScript文件注入到我们的视图中.
的WebPack-HTML-的WebPack-plugin.config.js
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
const viewPath = path.resolve(
__dirname,
"../Server/WebApplication/Views/Home"
);
...
entry: {
polyfills: `${entryPath}/polyfill.ts`,
vendors: `${entryPath}/vendor.ts`,
module1: `${module1}/main.ts`
},
output: {
path: corePath,
filename: "[name].[hash].js",
sourceMapFilename: "[name].[hash].js.map"
}
....
plugins: [,
...,
new HtmlWebpackPlugin({
template: viewPath + "/loader.cshtml",
filename: viewPath + "/Module1.cshtml",
inject: false
})
]
Run Code Online (Sandbox Code Playgroud)
在与指定视图相同的文件夹中,我们创建了一个名为的cshtml文件 loader.cshtml
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script src="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>
<my-angular-app>
Loading...
</my-angular-app>
Run Code Online (Sandbox Code Playgroud)
并npm run build:html
按照定义运行package.json
.如果它成功运行,结果将如此.
@{
ViewBag.Title = "Module 1";
}
<script src="../../Scripts/ng2/vendors.1470de344a0f2260b700.js"></script>
<script src="../../Scripts/ng2/vendors.1470de344a0f2260b700.js"></script>
<script src="../../Scripts/ng2/module1.1470de344a0f2260b700.js"></script>
<my-angular-app>Loading....</my-angular-app>
Run Code Online (Sandbox Code Playgroud)
II.定义了您自己的JavaScript版本
在我们的ASP.NET MVC项目中有点不同,因为我们使用了多个Angular应用程序.因此,我们在类中定义了一个版本,并在加载JS时将其附加到文件的末尾.通过这样做,我们将确保将最新的内容加载到浏览器中.但它不属于这个问题,所以我不会再进一步了.基本上,它看起来像下面的代码.
<script src="@string.Format("{0}?v={1}", "~/Scripts/ng2/polyfills.js", VersionHelper.CurrentVersion())</script>
<script src="@string.Format("{0}?v={1}", "~/Scripts/ng2/vendors.js", VersionHelper.CurrentVersion())</script>
<script src="@string.Format("{0}?v={1}", "~/Scripts/ng2/module1.js", VersionHelper.CurrentVersion())</script>
Run Code Online (Sandbox Code Playgroud)
在浏览器上提供它时,它看起来像
<script src="~/Scripts/ng2/polyfills.js?v=1.1.0"></script>
<script src="~/Scripts/ng2/vendors.js?v=1.1.0"></script>
<script src="~/Scripts/ng2/module1.js?v=1.1.0"></script>
Run Code Online (Sandbox Code Playgroud)
III.ASP.NET捆绑
在Zyllem,我们的团队没有使用它,因为我们的JavaScript文件在模型内部配置并稍后将其呈现给视图.
您可以App_Start\BundleConfig.cs
在项目中打开并配置一个包.让我们说名字是module1
bundles.Add(new ScriptBundle("~/bundles/module1").Include(
"~/Scripts/ng2/polyfills.js",
"~/Scripts/ng2/vendors.js"
"~/Scripts/ng2/module1.js"));
Run Code Online (Sandbox Code Playgroud)
通过这样做在视图内部渲染.
Index.cshtml
@Scripts.Render("~/bundles/module1")
Run Code Online (Sandbox Code Playgroud)
因此,当在浏览器上提供服务时,它将在末尾具有唯一标记,并且它是不同的如果您在脚本包中进行任何更改.
<script src="/bundles/module1?v=2PbUw0z_gh_Ocp_Vz13rdmmBSG6utLJAXm2lThxYAow1"></script>
Run Code Online (Sandbox Code Playgroud)
如果一切正常,您将看到以下屏幕截图.
更新
在Github上添加存储库https://github.com/trungk18/mvc5-angular-webpack