webpack 從入門到上樹
webpack 是什么
一項技術、一個工具的出現,肯定是為了解決問題的。那么,webpack 是為什么解決什么問題?答案是: 文件依賴管理 。我們在瀏覽器中的 js 中,不能直接引用其它 js, css 等文件(或說,模塊)。而 webpack 就是用來解決這個問題的,讓你的項目可以很好地分文件、分模塊,而且它對外部文件的引入同時支持 cmd, amd 和 commondJs 這三種形式,夠有誠意。
或許你要說了,解決文件依賴,早在 require.js 和 sea.js 的時候,都已經解決了呀!那么,webpack 在這方面,有哪些新的突破:
-
支持依賴各種拓展名的文件
-
能夠在不依賴 gulp 或 grunt 的情況下直接產出打包文件
-
支持實時編譯,瀏覽器同步刷新
這個時候,是不是很想唱一下王力宏的《唯一》:確定你就是我的唯一!
OK,進入正題。
安裝與運行
目前,我們的項目目錄結構是這樣的:
webpack_demo
|--src
| |--pages
| | |--index
| | | |--index.js
|--views_dev
| |--index.html
|--webpack.config.js
|--package.json
安裝
在項目的根目錄執行:
$ npm init // 生成項目依賴文件配置 package.json
$ npm install webpack -g // 全局安裝webpack
$ touch webpack.config.js // 在項目根目錄下,新建 webpack.config.js 文件
配置
然后,在以下3個文件,輸入內容:
-
頁面 HTML 文件
// views_dev/index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>首頁</title> </head> <body> <div>哈嘍,world</div> <script src="../asset/dev/main.js"></script> </body> </html>
-
頁面引用的 js 文件
// src/pages/index/index.js console.log('I am in index/index.js, haha4');
-
webpack 打包配置
// webpack.config.js module.exports = { // 入口:要進行處理的實例(js) entry: './src/pages/index/index.js', // 出口:輸出配置 output: { // 輸出到哪個目錄 path: './asset/dev/', // 靜態資源的引用路徑 publicpath: '/asset/dev/', // 實例最終輸出的名字 filename: '[name].js' } };
運行
運行 webpack 命令,進行打包。
$ webpack
然后,搞定了,此時在瀏覽器中打開 views_dev/index.html ,你會發現,打包成功了!
好的,你入門了的,哈哈!接下去,我會詳細介紹單個頁面打包、多個頁面打包,以及最后的發布上線。Now, go ~
單個頁面打包
這里,你將學到:
-
引入其它 js 文件。是的,你將學會 模塊化 。
-
引入其它類型的文件,以 css 為例。
-
實時編譯 + 瀏覽器同步刷新。爽!
現在,我們的項目目錄,是這樣:
webpack_demo
|--src
| |--pages
| | |--index
| | | |--index.js
| | | |--test.js
| | | |--index.css
| |--plugins
| | |--dialog
| | | |--dialog.css
| | | |--dialog.js
|--views_dev
| |--index.html
|--webpack.config.js
|--package.json
引入其它 js 文件
-
使用相對路徑
現在,我們要在 src/pages/index.js 里面引入 src/pages/test.js 文件。這樣做就可以了:
var Test = require('./test.js');
你也許會問,此時, var Test 這個變量,得到的是什么?換個說法,怎么控制 test.js 被導出到外部的內容。答案是:通過 module.exports . 例如:
// index/test.js var str = "I am in test.js"; module.exports = str;
那么, require('./test.js') 的值就是 "I am in test.js" 這個字符串。 module.exports 可以導出任何值。比如,我們要導出 Object.
module.exports = { aa: 'axxx', b: function() {} };
-
使用絕對路徑(別名的使用)
如果只能使用相對路徑,那 webpack 就太不靠譜了。因為將有可能出現這樣 ../../../../libs/libs-tost/toast.js , 啊,想死!那么,怎么使用呢?假如,我們想引入 src/plugins/dialog/dialog.js 這個彈窗。
-
在 webpack.config.js 中,配置別名
// webpack.config.js module.exports = { resolve: { // 定義別名 alias: { plugins: 'D:/your/path/webpack_demo/src/plugins' } } }
-
可以使用了
// src/index/index.js var Dialog = require('plugins/dialog/dialog.js');
當 require() 的第一單詞是 alias 中的,將被匹配。
-
引入其它類型的文件
webpack 的強大之處是,它允許你引入任何文件,比如:css, jpg, png. 那么,問題來了,對于不同的文件,它要怎么知道該如何分開處理呢?
// webpack.config.js
module.exports = {
module: {
loaders: [{
test: /\.css$/,
loader: 'style!css'
}, {
test: /\.js$/,
loader: 'babel'
}]
}
};
上面的配置是說,對于拓展名是 .css 的文件,使用加載器 style!css (這邊中間有一個感嘆號,意思是:先是用 css 加載器處理,然后使用 style 加載器處理)。完整的寫法是: style-loader!css-loader , 其中, -loader 可以省略。而這里的, style-loader 和 css-loader 就需要你 npm 安裝下了。
$ npm i style-loader -D
$ npm i css-loader -D
對于其它拓展名的處理,也是用同樣的方式來處理。
釋放雙手:自動編譯 + 瀏覽器同步刷新
你肯定希望,這樣的功能。那么,開始吧,喝杯咖啡!
-
自動編譯
如果你只是想支持自動編譯,那么很簡單。只要運行 $ webpack -w 就可以開啟它的自動編譯功能。
-
用 webpack-dev-server 實現:自動編譯 + 瀏覽器同步刷新
-
首先,你需要安裝 webpack-dev-server 這個包。
$ npm i webpack-dev-server -D
-
然后,我簡單介紹下它: webpack-dev-server 文檔
-
運行時,它會啟動一個本地 Node 服務器,默認端口8080. 即:localhost:8080. 并且自動識別當前目錄下的 webpack.config.js 文件,來作為 webpack 配置文件。
-
產出的編譯后文件,不在 output.path 里,而在它自己定義的內存。
-
行內參數說明:
-
inline: 使用命令行模式。
-
content-base: 指定網站的根地址,如果你想指定為項目根目錄,那么 --content-base ./
-
hot: 開啟熱替換。一般用在 React 和 Vue 當中,我們這里不用。
-
-
好了,那么,啟動它吧:
$ webpack-dev-server --inline --content-base ./
然后,你在瀏覽器中,訪問 http://localhost:8080/views_dev/index.html 就會發現,你修改代碼的時候,實時編譯,并且瀏覽器同步刷新了。
-
多頁面打包
現在,我們加一點點配置,讓它支持多個頁面打包。之前,它是這樣的:
module.exports = {
// 入口:要進行處理的實例(js)
entry: './src/pages/index/index.js',
// 出口:輸出配置
output: {
// 輸出到哪個目錄
path: './asset/dev/',
// 靜態資源的引用路徑
publicpath: '/asset/dev/',
// 實例最終輸出的名字
filename: '[name].js'
},
// 其它配置...
};
現在,我們需要改下 entry 的配置,如下:
entry: { index: './src/pages/index/index.js', list: './src/pages/list/index.js', common: [ './src/base/base.js', './src/base/base.css' ] }
上面的配置意思是,會獨立打包3個實體。分別是 index, list, common. 知識點如下:
-
它支持多個文件打包在一起,如這里的 common 的配置。我們一般,用來放公共基礎包。
-
我們看到 output.filename = [name].js ,這里的 [name] 取自于 entry 的 key 值。意味著,他們最終打包的輸出是:
webpack_demo |--asset | |--dev | | |--index.js | | |--list.js | | |--common.js
上線
發布上線,需要做什么呢?也許是這樣:
-
把靜態資源生成到一個獨立的目錄下
-
壓縮
-
加上 md5
-
html 和 css 中,引用的靜態資源需要替換。
哈哈,或許你還能想到很多。我就上面4步來說下實現方式。開始之前,我們一般會這么做:新建一個 webpack 的配置文件,用來做上線發布的配置。比如,我們同樣放在根目錄下,命名 webpack.config.build.js . 此時,你可以這樣做:
$ webpack -p --config webpack.config.build.js
這里的 -p 是 production 模式的意思,它會對 css, js 文件進行壓縮。后面 --config 就是指定此次運行的配置文件。
然后,我們來解決上面的4個要求:
-
把靜態資源生成到一個獨立的目錄下 + md5
// webpack.config.build.js module.exports = { output: { path: './asset/build/', // 文件編譯輸出路徑改成 build publicpath: 'http://yourweb.com/asset/build/', // 這里替換成線上實際地址,可以修改 css 中對圖片資源的引用路徑。 filename: '[name]_[hash:5].js' // 生成的文件名字,加上了5位的 hash值。 }, // 其它配置... };
-
壓縮。已經用 webpack -p 解決了。
-
替換靜態資源的路徑。可以用 webpack 的插件, html-webpack-plugin 來做。或者,你對 gulp 還是比較熟悉的話,用 gulp-prefix 來實現。這里就不詳細寫配置了。
然后,恭喜你看完了!
來自:https://segmentfault.com/a/1190000006649986
Save