Webpack在APS.NET mvc中使用

前戲亂侃:

話說因爲某js引擎獲得推廣,使js得以脫離瀏覽器,可在本地很好執行,因而乎NodeJS出現了。js能夠開發本地應用了,開發這種應用那得有不少js文件吧,總要分分模塊纔好管理吧,模塊分了以後,模塊之間怎麼引入呢?java中能夠用import,C#中能夠用using。嗯,js應用中就用require("path/to/module")吧,總應該爲之定個規範吧,因而這種js引入方式就被定義爲了CommonJS。後來某人受到啓發,既然本地應用中能夠這樣子引用,web App中能否也使用這樣的規範。因而require("path/to/module",function(){})這種web js引入方式得以應用,名曰AMD規範,大概的意思就是,模塊加載好後,執行後面的方法。以此同時也出現了另外一個模塊加載規範CMD。其實AMD和CMD規範都差很少,都是用於web的模塊加載器,AMD使用的加載器是RequireJS,CMD使用的加載器是SeaJS,RequireJS老外用得比較多,SeaJS國人用得比較多。再後來出現Grunt,Gulp,Webpack的打包工具。NodeJS是什麼,其實他就至關於能讓js在命令行執行的工具。以上亂侃over,懂得很少,不對之處,請指正。javascript

正文開始

當我還在興奮的追隨SeaJS時,甚至都還沒開始搞清楚時,已經開始有人宣判了SeaJS的死刑。在使用SeaJS開發一段時間後,是的,我贊同了這個觀點,特別是在模塊的打包方面,我至今仍是沒有找到一個好的解決方案(多是我知識不夠)。感受SeaJS只作到了模塊的分解,卻沒有找處處理模塊合併很好的解決方案。說白了SeaJS只是一個加載器,並非一個打包工具,它缺的就是一個打包工具。直到後來看到了webpack,在初步瞭解了一下他的功能後,我真的欣喜若狂,感受這就是我苦苦尋求的前端構建解決方案。css

想一下開發單頁面應用程序時,咱們的需求:html

  • 一、咱們但願每一個view只加載與之相關的資源,,其餘view用到的資源在點擊首次進入頁面時再加載,從而減小頁面資源的請求,提升頁面加載速度;
  • 二、引入其餘插件時,咱們但願在首次引入插件時,同時把插件用到css引入到頁面中,好比 art dialog 插件,重複引用,不會從新加載;
  • 三、css,image,js編譯、壓縮打包、生成版本號,自動替換,並加入到html或schtml中。

是的,webpack都能知足了以上的需求。除了以上的功能外,它還支持各類模塊的引入方式自然的支持CommonJS、AMD、CMD,但EA6須要引入相關的loader。前端

也就是說在一個模塊之中,你可使用如下的定義方式:java

 

說了這麼多,上一個我在用的配置方案。自動化構建,說白了玩的就是配置呀,配置好了就是一勞永逸了。node

個人方案是:Asp.net mvc+backbone+bootstrapjquery

Asp.net mvc...不解釋了;webpack

backbone:單頁面應用路由,前端mvc等;git

bootstrap 前端css框架。github

配置文件的大概思路:

首先我但願登陸和主應用的入口是分開的,所以設置了兩個程序入口;但這兩個入口都同時須要jQuery,所以我將jQuery單獨提取出來;

其次,我給mvc View設置了一個模板:views/home/index_tpl.cshtml。每次修改view時只須要修改模板就能夠了,構建完後會生成目標頁面views/home/index.cshtml,此時index.cshtml中會自動加入各類入口文件

//index_tpl.cshtml
@{
ViewBag.Title = "後臺管理-首頁";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div class="aliyun-console-topbar">
</div>
<div class="container-body sidebar-full">
<div class="sidebar"></div>
<div class="main" id="main">
</div>
</div>
</body>
</html>

 

//構建完後的index.cshtml,webpack會插入各類入口文件
@{
ViewBag.Title = "後臺管理-首頁";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>後臺管理 . NOCOQ</title>
<link href="/administration/dist/styles/vendors.90866b.css" rel="stylesheet"><link href="/administration/dist/styles/index.2e18b3.css" rel="stylesheet"></head>
<body>
<div class="aliyun-console-topbar">
</div>
<div class="container-body sidebar-full">
<div class="sidebar"></div>
<div class="main" id="main">
</div>
</div>
<script type="text/javascript" src="/administration/dist/vendors.7cf649.js"></script><script type="text/javascript" src="/administration/dist/index.7cf649.js"></script></body>
</html>

最後,說一個小插曲,使用webpack生成目標view後,運行起來後發現中文竟然是亂碼,找了很久才發現原來是由於webpack生成的文件編碼是utf-8 無 bom(utf-8 without bom)格式,而mvc的.cshtml的格式是utf-8 bom格式。因而找到了webpack-utf8-bom這個plugin才順利的解決了問題。

其餘的信息,備註中都有了。

使用webpack資源的引入、加載和打包,一切都這麼天然,我還能不喜歡它嗎?

 

//package.json 好像有點不全,不全就按webpack.config.js中找吧。

{ "name": "src", "version": "1.0.0", "description": "000", "main": "webpack.config.js", "dependencies": { "babel-core": "^6.17.0", "babel-loader": "^6.2.5", "babel-preset-es2015": "^6.16.0", "bootstrap": "^3.3.7", "css-loader": "^0.25.0", "expose-loader": "^0.7.1", "html-webpack-plugin": "^2.22.0", "jquery": "^3.1.1", "jquery-ui": "^1.12.1", "loader-utils": "^0.2.16", "lodash": "^4.16.4", "style-loader": "^0.13.1", "wangeditor": "^2.1.22", "webpack": "^1.13.2" }, "devDependencies": { "art-template": "^3.0.3", "art-template-loader": "^0.1.4", "backbone": "^1.3.3", "clean-webpack-plugin": "^0.1.13", "copy-webpack-plugin": "^3.0.1", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.9.0", "html-webpack-plugin": "^2.22.0", "mime": "^1.3.4", "underscore": "^1.8.3", "url-loader": "^0.5.7" }, "scripts": { "test": "" }, "author": "", "license": "ISC" }

  

//webpack.config.js

var path = require('path'); var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); // 自動寫入將引用寫入html var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin"); // 提取公共模塊 var ExtractTextPlugin = require("extract-text-webpack-plugin");// 提取/分離css var CleanWebpackPlugin = require('clean-webpack-plugin'); // 刪除文件 var CopyWebpackPlugin = require('copy-webpack-plugin'); // 拷貝文件 var BomPlugin = require('webpack-utf8-bom');//將文件轉成utf-8 bom格式,解決中文亂碼的問題 //console.log(require.resolve("bootstrap")); //定義了一些文件夾的路徑 var ROOT_PATH = path.resolve(__dirname); var CTRL_ROOT_PATH = path.resolve(__dirname, "administration"); var CTRL_SRC_PATH = path.resolve(CTRL_ROOT_PATH, 'dev'); var CTRL_DIST_PATH = path.resolve(CTRL_ROOT_PATH, 'dist'); //console.log(CTRL_ROOT_PATH) module.exports = { entry: { index: path.resolve(CTRL_SRC_PATH, 'index.js'), login_index: path.resolve(CTRL_SRC_PATH, 'login_index.js'), vendors: ['jquery', 'datepicker'], //"jquery-ui": ["jquery-ui/themes/base/core.css", "jquery-ui/themes/base/datepicker.css", "jquery-ui/themes/base/theme.css"], //"style": [path.resolve(CTRL_SRC_PATH, 'styles/style.css')], }, output: { //context: path.resolve(__dirname, 'scripts'), path: path.resolve(CTRL_DIST_PATH), publicPath: '/administration/dist/',//當生成的資源文件和站點不在同一地方時須要配置改地址 e.g.:站點在src,資源生成到/src/static/dist,那麼publicPath="/static/dist" filename: "[name].[hash:6].js", chunkFilename: "[id].chunk.js", }, plugins: [ //new webpack.ProvidePlugin({$: 'jquery'}), new ExtractTextPlugin("styles/[name].[contenthash:6].css", { allChunks: false }), new HtmlWebpackPlugin({ title: '後臺管理', template: path.resolve(CTRL_ROOT_PATH, 'views/home/index_tpl.cshtml'), filename: path.resolve(CTRL_ROOT_PATH, 'views/home/index.cshtml'), chunks: ['index', 'vendors'], // 配置要添加的模塊 inject: 'body' }), new HtmlWebpackPlugin({ title: '登陸後臺管理', template: path.resolve(CTRL_ROOT_PATH, 'views/account/login_tpl.cshtml'), filename: path.resolve(CTRL_ROOT_PATH, 'views/account/login.cshtml'), chunks: ['login_index', 'vendors'], // 配置要添加的模塊 inject: 'body' }), new CommonsChunkPlugin('vendors', 'vendors.[hash:6].js'), new CleanWebpackPlugin(['dist', 'build'], { root: CTRL_ROOT_PATH, verbose: true, dry: false, //exclude: ["dist/1.chunk.js"] }), new BomPlugin(true, /\.(cshtml)$/),//解決cshtml中文亂碼的問題 ], module: { /***解決動態路徑警告的問題***/ // require unknownContextRegExp: /$^/, unknownContextCritical: false, // require(expr) exprContextRegExp: /$^/, exprContextCritical: false, // require("prefix" + expr + "surfix") wrappedContextRegExp: /$^/, wrappedContextCritical: false, /***end****/ loaders: [ { test: require.resolve('jquery'), loader: 'expose?$!expose?jQuery' }, // 將jQuery暴露到全局變量中 { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?' + JSON.stringify({ discardComments: { removeAll: true } })) }, { test: /\.(png|jpg|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9]+)?$/, loader: 'url-loader?limit=1000&name=fonts/[name].[hash:6].[ext]' }, // 處理圖片url //{ test: /\.(png|jpg|gif)(\?[a-z0-9]+)?$/, loader: 'url-loader?limit=1000&name=images/[name].[hash:8].[ext]' }, // 處理圖片url limit=1000 小於1kb則生成base64 //{ test: /\.css$/, loader: "style!css" }, { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel', // 'babel-loader' is also a valid name to reference query: { presets: ['es2015'] } }, { test: /\.tpl/, loader: 'art-template-loader' }, ] }, resolve: { alias: { "datepicker": "jquery-ui/ui/widgets/datepicker", } } };

 參考資料:

Webpack https://webpack.github.io/docs/

NodeJS https://nodejs.org/

Grunt http://gruntjs.com/

Gulp http://gulpjs.org/

SeaJS http://seajs.org/docs/

RequireJS http://requirejs.org/

相關文章
相關標籤/搜索