1. 程式人生 > 資訊 >水星推出 X30G 無線路由器:四天線獨立 FEM,225 元

水星推出 X30G 無線路由器:四天線獨立 FEM,225 元

一、全面理解webpack 1、什麼是webpack? webpack是近期最火的一款模組載入器兼打包工具,它能把各種資源,例如JS(含JSX)、coffee、樣式(含less/sass)、圖片等都作為模組來使用和處理,它能有Grunt或Gulp所有基本功能。webpack的官網是https://webpack.github.io/,文件地址是https://webpack.github.io/docs,官網對webpack的定義是MODULE BUNDLER,他的目的就是把有依賴關係的各種檔案打包成一系列的靜態資源。 請看下圖: 2、webpack的優勢 其優勢主要可以歸類為如下幾個:
  1. webpack是以commonJS的形式來書寫指令碼滴,但對AMD/CMD的支援也很全面,方便舊專案進行程式碼遷移。
  2. 支援很多模組載入器的呼叫,可以使模組載入器靈活定製,比如babel-loader載入器,該載入器能使我們使用ES6的語法來編寫程式碼;less-loader載入器,可以將less編譯成css檔案;
  3. 開發便捷,能替代部分grunt/gulp的工作,比如打包、壓縮混淆、圖片轉base64等。
  4. 可以通過配置打包成多個檔案,有效的利用瀏覽器的快取功能提升效能。
3、wepback它的目標是是什麼? webpack它能將依賴的模組轉化成可以代表這些包的靜態檔案
  • 將依賴的模組分片化,並且按需載入
  • 解決大型專案初始化載入慢的問題
  • 每一個靜態檔案都可以看成一個模組
  • 可以整合第三方庫
  • 能夠在大型專案中運用
  • 可以自定義切割模組的方式

4、webpack較之其他類似工具有什麼不同?

  • 有同步和非同步兩種不同的載入方式
  • Loader,載入器可以將其他資源整合到JS檔案中,通過這種方式,可以講所有的原始檔形成一個模組
  • 優秀的語法分析能力,支援CommonJsAMD規範
  • 有豐富的開源外掛庫,可以根據自己的需求自定義webpack的配置

5、webpack為什麼要將所有資源放在一個檔案裡面?

我們知道,對於瀏覽器來說,載入的資源越少,響應的速度也就越快,所以有時候我們為了優化瀏覽器的效能,會盡可能的將資源合併到一個主檔案app.js裡面。但是這導致的很大的缺點:

  • 當你的專案十分龐大的時候,不同的頁面不能做到按需載入,而是將所有的資源一併載入,耗費時間長,效能降低。
  • 會導致依賴庫之間關係的混亂,特別是大型專案時,會變得難以維護和跟蹤。比如:哪些檔案是需要A模組載入完後才能執行的?哪些頁面會受到多個樣式表同時影響的?等許多問題。

而webpack可以很好的解決以上缺點,因為它是一個十分聰明的模組打包系統,當你正確配置後,它會比你想象中的更強大,更優秀。

二、開啟wbpack之旅 安裝步驟如下:

1、生成package.json檔案;

先裝好node和npm,因為webpack是一個基於node的專案。然後首先我們需要在根目錄下生成package.json檔案,需要進入專案檔案內根目錄下執行如下命令:npminit

如上通過一問一答的方式後會在根目錄下生成package.json檔案,如下所示:

2.通過全域性安裝webpack 執行命令如下:npminstall-gwebpack如下所示: 在c盤下會生成node_modules資料夾中會包含webpack,此時此刻我們可以使用webpack命令了; 在常規專案中把webpack依賴加入到package.json npminitnpminstallwebpack--save 更詳盡的安裝方法個可以參考webpack安裝 3.配置webpack 每個目錄下都必須有一個webpack.config.js,它的作用就好比Gulpfile.js、或者Gruntfile.js,就是一個專案配置,告訴webpack需要做什麼。 首先先貼上一個比較完整的webpack.config.js的程式碼,再詳細介紹:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 //詳細的webpack.config.js結構分析: varpath = require('path'); varwebpack = require('webpack'); varHtmlWebpackPlugin = require('html-webpack-plugin'); varTransferWebpackPlugin = require('transfer-webpack-plugin'); module.exports = { devtool:'source-map',//由於打包後的程式碼是合併以後的程式碼,不利於排錯和定位,只需要在config中新增,這樣出錯以後就會採用source-map的形式直接顯示你出錯程式碼的位置。 //noParse:[/jquery/],//表示跳過jquery,不對其進行編譯,這樣可以提高打包的速度 //頁面入口檔案配置 entry: { page1:"./src/index.js", //page2: ["./src/index.js", "./src/main.js"],支援陣列形式,將載入陣列中的所有模組,但以最後一個模組作為輸出 }, //入口檔案輸出配置 output: { path:"dist/js/page", filename:"[name].bundle.js",// page1.bundle.js 和 page2.bundle.js,並存放到 ./dist/js/page 資料夾下。 publicPath:"/dist/"//網站執行時的訪問路徑。 }, resolveLoader: { //指定預設的loader路徑,否則依賴走到上游會找不到loader root: path.join(__dirname,'node_modules'), alias: {//給自己寫的loader設定別名 "seajs-loader": path.resolve( __dirname,"./web_modules/seajs-loader.js") } }, //新建一個開發伺服器,並且當代碼更新的時候自動重新整理瀏覽器。 devServer: { historyApiFallback:true, noInfo:true, hot:true, inline:true, progress:true, port:9090//埠你可以自定義 }, module: { // module.loaders 是最關鍵的一塊配置。它告知 webpack每一種檔案都需要使用什麼載入器來處理: loaders: [ { test: /\.css$/, loader:'style-loader!css-loader'},//.css 檔案使用 style-loader 和 css-loader 來處理. //{ test: /\.css$/, loader: 'style!css' },其他寫法1、"-loader"其實是可以省略不寫的,多個loader之間用“!”連線起來。 //{ test: /\.css$/, loaders: ["style", "css"] },其他寫法2、用loaders陣列形式; //.scss 檔案使用 style-loader、css-loader 和 sass-loader 來編譯處理。 //在chrome中我們通過sourcemap可以直接除錯less、sass原始檔檔案 { test: /\.scss$/, loader:'style!css!sass?sourceMap'}, { test: /\.less$/, loader:'style!css!less?sourceMap'},//.less 檔案使用 style-loader、css-loader 和 less-loader 來編譯處理 //.js 檔案使用babel-loader來編譯處理,設定exclude用來排除node_modules這個資料夾中的程式碼 { test: /\.js$/, loader:'babel!jsx',exclude: /node_modules/ }, { test: /\.jsx$/, loader:"jsx-loader?harmony"},//.jsx 檔案使用 jsx-loader 來編譯處理 { test: /\.json$/,loader:'json'}, //{ test: /\.(png|jpg|jpeg|gif)$/, loader: 'url-loader?limit=8192'},//圖片檔案使用 url-loader 來處理,小於8kb的直接轉為base64 {test: /\.(png|jpg|gif|svg)$/,loader:'url', query: {limit: 10000,name:'[name].[ext]?[hash]'}//設定圖片名稱副檔名 }, { test: /\.jade$/, loader:"jade-loader"},//.jade 檔案使用 jade-loader 來編譯處理 { test: /\.ejs$/, loader:"ejs-loader"},//.ejs 檔案使用 ejs-loader 來編譯處理 { test: /\.handlebars$/, loader:"handlebars-loader"},//.handlebars 檔案使用handlebars-loader來編譯處理handlebars模板檔案 { test: /\.dot$/, loader:"dot-loader"},//.dot 檔案使用 dot-loader 來編譯處理dot模板檔案 { test: /\.vue$/, loader:"vue-loader"},//.vue 檔案使用 vue-loader 來編譯處理 { test: /\.coffee$/, loader:'coffee-loader'},//.coffee 檔案使用 coffee-loader 來編譯處理 { test: /\.html$/,loader:'vue-html'}, { test: /\.woff$/,loader:"url?limit=10000&minetype=application/font-woff"}, { test: /\.ttf$/,loader:"file"}, { test: /\.eot$/,loader:"file"}, { test: /\.svg$/,loader:"file"} ] }, //分內建外掛和外接外掛 plugins: [ //使用了一個 CommonsChunkPlugin 的外掛,它用於提取多個入口檔案的公共指令碼部分,然後生成一個common.js來方便多頁面之間進行復用。 newwebpack.optimize.CommonsChunkPlugin('common.js'), newwebpack.optimize.UglifyJsPlugin({//壓縮檔案 compressor: { warnings:false,//supresses warnings, usually from module minification }, except: ['$super','$','exports','require']//排除關鍵字(可選) }), newwebpack.DefinePlugin({// definePlugin 接收字串插入到程式碼當中, 所以你需要的話可以寫上 JS 的字串 __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV ||'true')), __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE ||'false')) }), newwebpack.ProvidePlugin({//把一個全域性變數插入到所有的程式碼中,支援jQuery plugin的使用;使用ProvidePlugin載入使用頻率高的模組 //provide $, jQuery and window.jQuery to every script $:"jquery", jQuery:"jquery", "window.jQuery":"jquery" }), newwebpack.NoErrorsPlugin(),//允許錯誤不打斷程式 newTransferWebpackPlugin([//把指定資料夾下的檔案複製到指定的目錄 {from:'www'} ], path.resolve(__dirname,"src")), newHtmlwebpackPlugin({//用於生產符合要求的html檔案; title:'Hello World app', filename:'assets/admin.html' }) ], //其它解決方案配置 resolve: { root:'E:/github/flux-example/src',//絕對路徑, 查詢module的話從這裡開始查詢(可選) extensions: ['','.js','.html','.css','.scss'],//自動擴充套件檔案字尾名,意味著我們require模組可以省略不寫字尾名 alias: {//模組別名定義,方便後續直接引用別名,無須多寫長長的地址//後續直接 require('AppStore') 即可 AppStore :'js/stores/AppStores.js', ActionType :'js/actions/ActionType.js', AppAction :'js/actions/AppAction.js' }, modulesDirectories: [//取相對路徑,所以比起 root ,所以會多很多路徑。查詢module(可選) 'node_modules', 'bower_components', 'lib', 'src' ] } }; if(process.env.NODE_ENV ==='production') { module.exports.devtool ='#source-map' // http://vue-loader.vuejs.org/en/workflow/production.html module.exports.plugins = (module.exports.plugins || []).concat([ newwebpack.DefinePlugin({ 'process.env': { NODE_ENV:'"production"' } }), newwebpack.optimize.UglifyJsPlugin({ compress: { warnings:false } }), //為元件分配ID,通過這個外掛webpack可以分析和優先考慮使用最多的模組,併為它們分配最小的ID newwebpack.optimize.OccurenceOrderPlugin() ]) }

plugins中包含很多的內建外掛和外部外掛,它們都有各自的功能,用來處理相關的檔案,這裡只是羅列了部分,具體用法請看webpack入門和實戰(二):全面理解和運用plugins和loader

就像我在前面提到的,webpack.config.js的寫法和在Node裡的寫法相同,我們主要看的就是檔案中的module.exports裡面的內容
  • entry是指入口檔案的配置項,它是一個數組的原因是webpack允許多個入口點。
  • output是指輸出檔案的配置項
    • path-表示輸出檔案的路徑
    • filename-表示輸出檔案的檔名
  • plugins顧名思義,使用外掛可以給webpack新增更多的功能,使webpack更加的靈活和強大,webpack有兩種型別的外掛:
    • webpack內建的外掛
//首先要先安裝webpack模組
var webpack = require("webpack");
module.exports = {
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false,
      },
    })
};
    • webpack外接外掛
//npm install component-webpack-plugin 先要在安裝該模版
var ComponentPlugin = require("component-webpack-plugin");
module.exports = {
    plugins: [
        new ComponentPlugin()
    ]
}

更多的外掛以及外掛的用法,大家可以到webpack的外掛上檢視。

  • module配置處理檔案的選項
  • loaders一個含有wepback中能處理不同檔案的載入器的陣列
  • test用來匹配相對應檔案的正則表示式
  • loaders告訴webpack要利用哪種載入器來處理test所匹配的檔案
  • loaders的安裝方法
        $npminstallxxx-loader--save-dev
  • resolve:其它解決方案配置;
    • resolve.root,絕對路徑,查詢module的話從這裡開始查詢(可選)
    • resolve.modulesDirectories,取相對路徑,所以比起root,所以會多parse很多路徑。查詢module(可選)
    • resolve.extensions,自動擴充套件檔案字尾名,意味著我們require模組可以省略不寫字尾名
    • resolve.alias,模組別名定義,方便後續直接引用別名,無須多寫長長的地址
三、利用webpack實現在頁面上合理使用打包過後的js檔案和圖片 示例如下: webpack_test目錄結構如下: 最終完成版的目錄結構為: index.html程式碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo1</title>
</head>
<body>
    <div id="content"></div>
    <img src="./build/img/demo.png">
    <script src="./build/js/index.js"></script>
</body>
</html>

index.js程式碼如下:

require('./index.css');

index.css程式碼如下:

#content{
    width:121px;
    height:140px;
    background-color: red;
}
demo.png自己隨便找一張即可; 根據webpack.config.js的配置情況,操作步驟如下:
  • 全域性安裝webpack,npm install webpack -g
  • 進入到webpack_test目錄下,初始化生成package.json檔案,npm init
  • 需要安裝的loader有css-loader、style-loader、url-loader,webpack, npm install css-loader style-loader url-loader webpack--save-dev
  • 執行webpack,生成打包過後的build/js/index.js,build/img/demo.png
  • 在index.html中引入即可

效果如下:

原始碼地址為:http://download.csdn.net/detail/wdlhao/9612173,有需要的同學可以自行下載練習; 四、理解webpack支援commonJS和AMD/CMD兩種模組機制進行打包 1.AMD/CMD模式: AMD規範在這裡:https://github.com/amdjs/amdjs-api/wiki/AMD,CMD規範在這裡:https://github.com/seajs/seajs/issues/242
  • AMD(AsynchronousModuleDefinition)是RequireJS在推廣過程中對模組定義的規範化產出。(即RequireJS模組規範)
RequireJS是一個工具庫,主要用於客戶端的模組管理。它可以讓客戶端的程式碼分成一個個模組,實現非同步或動態載入,從而提高程式碼的效能和可維護性。它的模組管理遵守AMD規範(AsynchronousModuleDefinition)。RequireJS的基本思想是,通過define方法,將程式碼定義為模組;通過require方法,實現程式碼的模組載入。首先,將require.js嵌入網頁,然後就能在網頁中進行模組化程式設計了。<scriptdata-main="scripts/main"src="scripts/require.js"></script>上面程式碼的data-main屬性不可省略,用於指定主程式碼所在的指令碼檔案,在上例中為scripts子目錄下的main.js檔案。使用者自定義的程式碼就放在這個main.js檔案中。
  • CMD(CommonModuleDefinition)是SeaJS在推廣過程中對模組定義的規範化產出。(即SeaJS模組規範)
SeaJS是一個遵循CMD規範的JavaScript模組載入框架,可以實現JavaScript的模組化開發及載入機制。
  • CommonJSModules/2.0規範,是BravoJS在推廣過程中對模組定義的規範化產出。
CommonJSAPI定義很多普通應用程式(主要指非瀏覽器的應用)使用的API,從而填補了這個空白。它的終極目標是提供一個類似Python,Ruby和Java標準庫。這樣的話,開發者可以使用CommonJSAPI編寫應用程式,然後這些應用可以執行在不同的JavaScript直譯器和不同的主機環境中。在相容CommonJS的系統中,你可以實用JavaScript程式開發:
  • 伺服器端JavaScript應用程式
  • 命令列工具
  • 圖形介面應用程式
  • 混合應用程式(如,Titanium或AdobeAIR)

還有不少⋯⋯這些規範的目的都是為了JavaScript的模組化開發,特別是在瀏覽器端的。目前這些規範的實現都能達成瀏覽器端模組化開發的目的。

2、AMD/CMD模式區別

2.1從官方推薦的寫法上面得出:

CMD ----- 依賴就近

Js程式碼 
//CMD 
define(function(require,exports,module){ 
   var a = require('./a'); 
   a.doSomthing(); 
});

AMD ----- 依賴前置

Js程式碼 
//AMD 
define(['./a','./b'],function(a,b){ 
//...... 
a.doSomthing(); 
//...... 
b.doSomthing(); 
})

當然AMD也支援CMD的寫法。

2.2、執行順序上:

    • CMD是延遲執行,推崇的是aslazyaspossible
    • AMD是提前執行,requireJS從2.0開始可以延遲執行
2.3、api設計角度:
    • CMD的API推崇職責單一,沒有全域性的require
    • AMD的API預設是一個當多個用:比如require有全域性的和區域性的