這兩天學習了一些webpack的知識,loaders+plugins真的很強大!不過配置起來也很複雜,看了一些文章,自己也寫了專案練手,寫下來加深自己的印象。
首先,非常非常推薦的幾篇文章,初學者一定要看!
<入門Webpack,看這篇就夠了>
http://www.jianshu.com/p/42e1…
(標題一點也不誇張,非常適合0基礎)
<Webpack傻瓜式指南>
https://zhuanlan.zhihu.com/p/…
https://zhuanlan.zhihu.com/p/…
https://zhuanlan.zhihu.com/p/…
(這個系列有三篇文章,第三章是一個webpack+react的小專案,跟著做一遍會很有收穫~)
另外,也推薦看一下阮一峰es6書中module這一章,弄清楚export/import/export default等等命令,畢竟webpack的各個模組是靠export/import/require(commonjs)連結起來的,所以這些都要掌握。
具體到專案的話,webpack有幾個比較基本的概念:
1、loaders:通過不同的loaders,webpack可以處理各式各樣的檔案,然後打包到一個檔案中(比如bundle.js);
2、plugins:plugins是為了擴充webpack的功能的,和loaders不同的是,loader是用來處理單個檔案的(比如json-loader處理.json,sass-loader處理.scss),但是plugins是直接對整個構建過程進行處理(比如自動生成html檔案的html-webpack-plugin);
3、others: 這些我也不知道要歸到哪裡去,但是在配置中也是必不可少,包括webpack-dev-server/source-map等等,後面會具體說;
4、配置檔案:我這個小專案包括的檔案有.babelrc(用來處理babel),webpack.config.js(webpack專案基礎配置檔案),package.json(這個檔案會記錄所有的devDependencies)。
然後我們就一項一項來分析吧:
1、loaders
1) style-loader / css-loader / sass-loader
這幾個loader用來處理.css和.scss檔案,一起安裝用空格隔開:
$ npm install --save-dev style-loader css-loader sass-loader
同時修改webpack.config.js:
module: {
loaders: [
{
test: /.scss$/,
//loaders是依靠正規表示式來測試這個檔案是不是這個loader來處理,所以test不能少
loaders: [`style-loader`,`css-loader`,`sass-loader`],
//"-loader"一定要寫,不然會報錯
//loaders的處理順序是從右向左,就是會先用sass-loader,其次css-loader,再次style-loader
}
2) url-loader
這個loader是用來處理url連結,就是圖片或者其他靜態檔案。
安裝:
$ npm install --save-dev url-loader
webpack.config.js (寫在module裡):
{
test: /.(png|jpq)$/,
loader: `url? limit = 40000`
}
3) json-loader
安裝和配置和之前一樣~用來處理json檔案
4) babel相關的loaders:
這個包括的就比較多,有babel-core/babel-loader/babel-preset-es2015/babel-preset-react,後面兩個是為了寫es6和react服務。
//webpack.config.js
{
test: /.jsx$/,
loader:`babel-loader`,
include: APP_PATH,
//這個include是說只對這裡面的檔案負責,還有一個對應的exclude,就是忽略範圍內的檔案, 比如:exclude: `./node_modules/`;
}
另外因為babel需要寫的選項比較多,可以配一個.babelrc在根目錄下:
//.babelrc
{
`presets`:[`react`,`es2015`],
}
}
以上就是用的比較多的loaders,配完這些webpack就可以處理json/sass/es6啦~
2、plugins
1) html-webpack-plugin
這個外掛的作用就是自動生成html(其實也可以自己寫,就是加了個bundle.js的script而已,不過感覺比較酷):
plugins安裝好了之後要放在webpack.config.js的plugins的陣列裡,不要寫在modules裡呀~
//webpack.config.js
plugins: [
new HtmlWebpackPlugin({
//在最前面先定義下HtmlWebpackPlugin--
//var HtmlWebpackPlugin = require(`html-webpack-plugin`);
title: `searchBar`, //配合html-webpack-plugin的配置
})
],
2) react-transform-hrm
HMR是一個webpack外掛,它讓你能瀏覽器中實時觀察模組修改後的效果,但是如果你想讓它工作,需要對模組進行額外的配額;
Babel有一個叫做react-transform-hrm的外掛,可以在不對React模組進行額外的配置的前提下讓HMR正常工作;
安裝:
$ npm install --save-dev babel-plugin-react-transform react-transform-hmr
配置:
//webpack.config.js (plugins裡)
new webpack.HotModuleReplacementPlugin();
然後修改下.babelrc:
{
"presets": ["react", "es2015"],
"env": {
"development": {
"plugins": [["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}]
}]]
}
}
}
這樣在使用react的時候就可以熱載入模組了~
3)UglifyJsPlugin:
壓縮JS程式碼;
4)ExtractTextPlugin:
分離CSS和JS檔案;
以上兩個外掛這次沒有用,先記下來下次用過了再來補~
3、others
1) webpack-dev-server
用來構建本地開發的伺服器,可以讓瀏覽器監測程式碼的修改,並自動重新整理修改後的結果;
安裝:
$npm --save-dev webpack-dev-server
webpack-dev-server有以下幾個配置選項:
-
contentBase:預設webpack-dev-server會為根資料夾提供本地伺服器,如果想為另外一個目錄下的檔案提供本地伺服器,應該在這裡設定其所在目錄(本例設定到“public”目錄)
-
port:設定預設監聽埠,如果省略,預設為”8080“
-
inline:設定為true,當原始檔改變時會自動重新整理頁面
-
historyApiFallback:在開發單頁應用時非常有用,它依賴於HTML5 history API,如果設定為true,所有的跳轉將指向index.html
//webpack.config.js devServer: { contentBase: "./public",//本地伺服器所載入的頁面所在的目錄 historyApiFallback: true,//不跳轉 inline: true//實時重新整理 }
//package.json
"scripts": {
"start": "webpack-dev-server --inline",
}
然後就可以用http://localhost:8080/index.html預覽專案啦~
2)source-map:
source maps提供了一種對應編譯檔案和原始檔的方法,使得編譯後的程式碼可讀性更高,也更容易除錯。
在學習階段和寫中、小型專案的時候,用eval-source-map,如果是開發大型專案可以用cheap-module-eval-source-map,會更快。
//webpack.config.js
devtool: `eval-source-map`,
3) 第三方庫:
這個就包括一些我們比較瞭解的比如react/react-dom/jquery/moment/bootstrap等等啦,配置起來也很方便,首先是安裝:
$npm --save-dev jquery moment react react-dom
$npm install bootstrap@4.0.0-alpha.2 --save-dev
然後在你需要的js檔案裡引用這些庫:
import React from `react`;
import ReactDOM from `react-dom`;
var $ = require(`jquery`);
var moment = require(`moment`);
然後就可以愉快地寫各種js、jsx檔案啦~
4、配置檔案
最後我們來講一講幾個配置檔案的問題:
1) webpack.config.js
上面提到的都是各種肢解,我這次的config檔案是這樣的:
var path = require(`path`);
var HtmlWebpackPlugin = require(`html-webpack-plugin`);
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, `app`);
var BUILD_PATH = path.resolve(ROOT_PATH, `build`);
module.exports = {
devtool: `eval-source-map`,
entry: __dirname + `/app/index.jsx`,
//webpack的入口檔案只有一個,所以寫的所有components甚至包括css/json什麼的,都要引用在這裡
output:{
path: __dirname +`/public`,
filename: `bundle.js`,
},
//我這邊是新建了一個folder叫public,用來放index.html和bundle.js
devServer: {
contentBase: "./public",//本地伺服器所載入的頁面所在的目錄
historyApiFallback: true,//不跳轉
inline: true//實時重新整理
},
plugins: [
new HtmlWebpackPlugin({
title: `searchBar`, //配合html-webpack-plugin的配置
})
],
module: {
loaders: [
{
test: /.scss$/,
loaders: [`style-loader`,`css-loader`,`sass-loader`],
},{
test: /.(png|jpq)$/,
loader: `url? limit = 40000`
},{
test: /.jsx$/,
loader:`babel-loader`,
include: APP_PATH,
}]
},
resolve:{
extensions: [``,`.js`, `.jsx`]
},
};
2) package.json
這個檔案會在你最開始npm init的時候就生成,一路回車就可以,後來都可以改~
{
"name": "serach-bar",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --progress --profile --colors --hot",
"build": "webpack --progress --profile --colors",
"test": "karma start"
},
//scripts這邊可以改一下,改start可以,在終端用npm start,上面有例子~這邊的dev要改的話在終端的命令是`npm run dev;
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.22.1",
"babel-loader": "^6.2.10",
"babel-plugin-react-transform": "^2.0.2",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.22.0",
"babel-preset-react-hmre": "^1.1.1",
"bootstrap": "^4.0.0-alpha.2",
"css-loader": "^0.26.1",
"file-loader": "^0.10.0",
"html-webpack-plugin": "^2.28.0",
"jquery": "^3.1.1",
"jshint": "^2.9.4",
"jshint-loader": "^0.8.3",
"json-loader": "^0.5.4",
"node-sass": "^4.5.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-transform-catch-errors": "^1.0.2",
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.3.3",
"sass-loader": "^4.1.1",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.3.0"
}
}
裝了很多dev,其實用不著那麼多哈哈~
3) .babelrc
{
`presets`:[`react`,`es2015`],
`env`:{
`development`:{
`presets`:[`react-hmre`]
}
}
}
ok,這樣就差不多啦~另外還要注意的是index.jsx/index.js,所有的components都要引用過來,css/scss也是,css檔案的話最好有一個main.css進行整合,這樣不會漏掉。
看一眼這次的index.jsx:
// `注意這些import
import `../node_modules/bootstrap/scss/bootstrap.scss`;
import `./main.scss`;
import React from `react`;
import ReactDOM from `react-dom`;
import Search from `./components/search`;
import Plist from `./components/plist`;
class App extends React.Component{
constructor(props){
super(props);
this.state={`keyword`:``};
this.refreshKeyword = this.refreshKeyword.bind(this);
}
refreshKeyword(name){
this.setState({`keyword`:name});
}
render(){
return (
<div className = `container`>
<section className = `jumbotron`>
<h3 className =`jumbotron-heading`>Search Github Users</h3>
<Search sendAction = {this.refreshKeyword} />
</section>
<Plist keyword={this.state.keyword} />
</div>
)
}
};
const app = document.createElement(`div`);
document.body.appendChild(app);
ReactDOM.render(<App />, app);
恩,差不多就是這樣啦~~專案初始化的時候不要忘記npm install –save-dev webpack哦!coding愉快!