這兩天學習了一些webpack的知識,loaders+plugins真的很強大!不過配置起來也很複雜,看了一些文章,本身也寫了項目練手,寫下來加深本身的印象。css
首先,很是很是推薦的幾篇文章,初學者必定要看!
<入門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的小項目,跟着作一遍會頗有收穫~)html
另外,也推薦看一下阮一峯es6書中module這一章,弄清楚export/import/export default等等命令,畢竟webpack的各個模塊是靠export/import/require(commonjs)連接起來的,因此這些都要掌握。node
具體到項目的話,webpack有幾個比較基本的概念:
一、loaders:經過不一樣的loaders,webpack能夠處理各式各樣的文件,而後打包到一個文件中(好比bundle.js);
二、plugins:plugins是爲了拓展webpack的功能的,和loaders不一樣的是,loader是用來處理單個文件的(好比json-loader處理.json,sass-loader處理.scss),可是plugins是直接對整個構建過程進行處理(好比自動生成html文件的html-webpack-plugin);
三、others: 這些我也不知道要歸到哪裏去,可是在配置中也是必不可少,包括webpack-dev-server/source-map等等,後面會具體說;
四、配置文件:我這個小項目包括的文件有.babelrc(用來處理babel),webpack.config.js(webpack項目基礎配置文件),package.json(這個文件會記錄全部的devDependencies)。react
而後咱們就一項一項來分析吧:jquery
1) style-loader / css-loader / sass-loaderwebpack
這幾個loader用來處理.css和.scss文件,一塊兒安裝用空格隔開:es6
$ npm install --save-dev style-loader css-loader sass-loader
同時修改webpack.config.js:web
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
$ 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啦~
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文件;
以上兩個插件此次沒有用,先記下來下次用過了再來補~
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文件啦~
最後咱們來說一講幾個配置文件的問題:
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愉快!