Webpack目前官方發佈的最新版本是3.1.0,相對於2.0的版本,在語法上沒有變更,只是新增了功能。使用webpack,須要事先安裝node.js,並對node.js生態有一些基本的瞭解,好比(npm init 初始化項目,npm install 安裝一個包等等)。使用webpack一般有兩種方式:1. 命令行方式(CLI) , 2 script方式(推薦)。 兩種方式都須要理解webpack概念。javascript
webpack is a module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles - often only one - to be loaded by the browser.css
webpack是時下很火的js模塊化的打包工具。當用webpack處理你的應用時,它會遞歸的構建每一個模塊的依賴關係圖,而後把全部的這些依賴模塊打包到一個由數個小塊組成的文件中--一般只有一個(將被瀏覽器加載)html
It is incredibly configurable, but to get started you only need to understand Four Core Concepts: entry, output, loaders, and plugins.前端
雖然它是高度可配置的,可是初步使用你只須要理解下面這四個核心概念:入口,輸出,加載器,插件。默認狀況下,全部這些配置項,都保存在項目根目錄下一個名爲webpack.config.js的文件中。vue
The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point as the contextual root or the first file to kick off your app.java
所謂的入口,就是告訴webpack從哪裏開始並經過依賴關係圖得知要哪些文件要打包。你能夠理解爲應用程序最早讀取的文件。讀取這個文件以後,就會產生一個模塊依賴關係圖,那麼當前這個文件,就是依賴關係的根。node
webpack.config.jsreact
module.exports = { entry: './path/to/my/entry/file.js' };
上例告訴webpack從./path/to/my/entry/file.js開始打包,這是最簡單的一種入口形式,實際上,它是下面這種形式的簡寫webpack
module.exports = { entry : { main : './path/to/my/entry/file.js' } }
entry 還能夠是數組的方式git
module.exports = { entry: ['./path/to/my/entry/file.js'] };
這對於不想在js中引入css的狀況很是有用,好比:
module.exports = { entry: ['./path/to/my/entry/file.js','./path/to/my/entry/file.css'] };
若是是多頁應用或者想要提取公共代碼(CommonsChunkPlugin)的話,就須要使用下面這種入口方式:
module.exports = { entry: { pageOne: './src/pageOne/index.js', pageTwo: './src/pageTwo/index.js', pageThree: './src/pageThree/index.js' } }
固然,這裏也可使用數組的形式,同時引入樣式或其它文件
module.exports = { entry: { pageOne: ['./src/pageOne/index.js','./src/pageOne/index.css'], pageTwo: ['./src/pageTwo/index.js'], pageThree: ['./src/pageThree/index.js'] } }
以上就是關於入口這個概念和配置的所有內容了,更詳細的介紹請移步官方網站關於入口的擴展介紹 。 除了要告訴webpack要從哪一個文件開始打包以外,還要告訴它打包生成的文件存放在哪一個位置。因而就有了輸出的配置。
webpack的output屬性就是告訴webpack怎麼對待這些打包的代碼。
Configuring the output
configuration options tell webpack how to write the compiled files to disk. Note that, while there can be multiple entry
points, only one output
configuration is specified.
配置output屬性就是告訴webpack把編譯後的文件寫在磁盤的哪一個地方。注意一點,雖然入口中能夠配置成多個文件的形式,可是輸出只能指定一個。
--- 打包以後資源,並不老是寫在磁盤上,也多是在內存中,好比使用webpack-dev-server的時候。(譯者注)
webpack.config.js
const path = require('path'); module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js' } };
output有兩個屬性是必須的。
1. path 輸出路徑
path
to your preferred output directory. 一般是絕對路徑。2. filename 文件名
當入口是多個文件的時候,能夠用變量[name]代替固定的名字。這裏的name變量,對應entry中的key. ( 對於entry:配置成字符串的時候,輸出的文件名就是main,若是不明白,查看前面入口部分的介紹)
module.exports = { entry: { app: './src/app.js', search: './src/search.js' }, output: { filename: '[name].js', path: __dirname + '/dist' } }
在filename屬性中,除了[name]以外,還能夠用[hash],[contenthash]等內置變量, Tips ! [hash:8] 截取hash前8位
3. publicPath 虛擬路徑
若是你有一個域名或打算用CDN,可使用這個配置,若是你不知道,或暫時不打算用,能夠不寫。
output: { path: "/home/proj/cdn/assets/", publicPath: "http://cdn.example.com/assets/", filename:'[name].js' }
注意:若是配置了publicPath屬性,那麼本地資源路徑,都會被替換成publicPath所指定的地址 (譯者注)
Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you import
or 「load」 them. Thus, loaders are kind of like 「tasks」 in other build tools, and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript, or inline images as data URLs. Loaders even allow you to do things like import
CSS files directly from your JavaScript modules!
加載器用於將資源代碼轉換成模塊。它容許您在導入或「加載」它們時預處理文件。所以,加載器就像處理各類任務的小工具,它提供一個強大的方法來處理前端構建步驟。加載器能夠把不一樣類型的文件(好比typescript)轉換成javascript 或者把圖片處理成內聯的數據地址(如base64),加載器甚至能夠像導入js模塊同樣直接導入樣式文件。
加載器聽起來很歷害的樣子,不過它不能算是webpack的功能,若是要想在項目中導入樣式模塊,須要先安裝樣式的加載器(css-loader), 一樣的,要導入圖片要安裝文件加載器(file-loader)
在命令行中輸入:
npm install --save-dev css-loader
便可安裝樣式加載器,後面跟的參數--save-dev 表示將保存到package.json的開發環境依賴屬性中。對應還有一個--save表示安裝到生產環境。 package.json文件能夠經過手工建立,也可用npm init(推薦)
建立。更多關於package.json的介紹請移步這裏
webpack.config.js
module.exports = { module: { rules: [ { test: /\.css$/, use: 'css-loader' } ] } };
加載器位於module屬性中(適用於webpack2.0+), rules 是一個數組,裏邊能夠添加多個加載器(loader). 每個加載器用對象的方式組織,下面是一個更爲複雜的配置
module: { rules: [ { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true } } ] } ] }
每個加載器,都有各自對應的配置內容,好比css-loader的詳細配置請移步這裏 ,可是無論怎麼說,方法都是同樣的。須要指出的事,加載器,除了在webpack.config.js中配置以外,還能夠直接在js代碼中用行內加載的方式使用,好比
import Styles from 'style-loader!css-loader?modules!./styles.css'; //多個加載器之間用!進行分隔
不過這種方式寫起來很冗長,不推薦。還有一種方式,也一併提一下,在CLI方式中的使用
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
一樣的冗長,瞭解一下便可,實際項目中,大可能是使用webpack.config.js進行集中配置。
通常來講,一個加載器就能夠完成一個任務,好比file-loader 能夠加載文件到js的模塊中,但是咱們經常發現,加載css到js模塊中,除了使用css-loader以外,經常還有一個或多個附加的伴侶,好比這個style-loader。
這是爲何呢? 這實際上是由於樣式的使用有兩種方式,一種是內聯的方式,寫在html的style標籤中,還有一種是外鏈,經過link的方式引用。而咱們在開發環境中,css是做爲js的模塊打包進js文件中的。並且js要使用樣式,必須在html中插入style標籤,而後把樣式以字符串的形式插入標籤內。因此這裏須要用到兩個加載器,首先用css-loader把樣式讀取到js的模塊中,然用style-loader寫入style標籤中。因此也就出現了css-loader和style-loader成對使用的狀況。對於同時使用多個加載器的狀況,它們的調用順序是從右向左的。也就是說最早使用的要寫在最右邊,對於新式這個例子來講,就是style-loader!css-loader這樣寫。關於style-loader這個加載器,其實它還有一個少被人提起,卻很是有用的功能--熱替換,這部份內容後面再細說
有人不由要問,既然css能夠直接用link的方式使用,爲何不把css打包成獨立的css文件呢?這樣我就不須要用style-loader了,並且把樣式內聯在html中,看着不舒服。好吧,這就不得不引出webpack中的第四個概念了---插件
4、 插件 plugins
They also serve the purpose of doing anything else that a loader cannot do.
插件用於完成一些載器所不能作的事情。
其實這樣解釋不併是很嚴謹,可是插件,確實使的webpack更增強大了。回到前說的獨立樣式的問題,結合插件來作。
先安裝extract-text-webpack-plugin 這個插件
npm install --save-dev extract-text-webpack-plugin
var path = require('path'); var webpack = require('webpack'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); var node_modules_dir = path.resolve(__dirname, '../node_modules'); module.exports = { entry: { home:'./src/home.es6' }, module: { rules:[{ test:/\.css/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: ["css-loader","postcss-loader"] }) } ] }, output: { path: path.resolve(__dirname,"../dist"), filename: 'js/[name][hash:7].js' }, plugins: [ new ExtractTextPlugin({ filename: "css/[name].[contenthash].css" }), new webpack.optimize.UglifyJsPlugin() ], }
new webpack.optimize.UglifyJsPlugin() //用來壓縮代碼,這個是webpack送的,不須要單獨安裝, new ExtractTextPlugin 用來提取css到一個獨立的樣式文件,這個插件須要本身安裝,還要在loader中進行相應的改動,配合使用才能生效。值得注意的是,這樣一來,就牲犧了css的熱替換能力了。不過無所謂,這個插件通常用在生產環境打包。
這應當屬於webpack中比較高級的內容了,可是在開發中,結合熱替換一塊兒使用,會很方便。最簡單的使用方式是經過 webpack-dev-server --hot
關於這一部分的內容,參考我之前寫的一篇文章。官方介紹移步這裏這裏須要指出的是,並非加了--hot就能夠實現熱替換,這須要對應的加載器支持「熱替換」才行的。
好比前面說的樣式,style-loader是能夠支持熱替換的。並且對於js來講,雖然webpack不須要額外的加載器就能夠進模塊化,可是並不支持「熱替換", 若是使用react.js的話,能夠用react-hot-loader,若是用Vue的話,能夠用vue-loader。 若是該加載器不支持熱替,會降級爲自動刷新。所以,熱替換,並非自動刷新哦。
webpack3還比較新,若是以前使用webpack2的項目,直接升級到webpack3的話,須要當心了,有些加載器和插件可能不支持webpack3. 好比提取css爲獨立文件的插件,就不支持。webpack-dev-server也不支持 (至少在我寫這篇文章的時候仍是不支持的),可是不能因噎廢食,新技術最終會取替舊技術,這是行業趨勢。安於現狀,只會被淘汰。webpack的學習最好是本身寫一個簡單項目,把文章提到的和本身學到的loader,plugin都試試。把基本的概念和用法型明白以後,能夠安裝別人寫的比較優盤的項目拿來對照學習,好比Vue-cli。看看行業大牛們,是怎麼配置webpack的,他們都用了哪些插件和加載器。最後,我也提供一下本身練習的項目,作爲本篇的結尾。https://github.com/bjtqti/font-end-boilerplate.git