webpack的功能不少,打包js\css\html,壓縮,編譯less\sass,自動生成版本號等等,由於能夠使用CommonJS等規範,能夠和react很好地配合使用。
它的使用方法比gulp要複雜,可是能作的事情也要比gulp更多一些~~
webpack本身有插件,經常使用的好比commonsPlugin、UglifyJsPlugin、ExtractTextPlugin、HtmlWebpackPlugin
等,實際項目中,也須要使用node自帶的一些模塊,好比path、glob
等,這些模塊具體在下面講。css
通過webpack打包後,生成的html、css、js文件都放在dist文件夾下,以dist/css、dist/js、dist/html
這樣的方式。html
安裝和使用就不說了,網上教程很詳細,這裏只提一點,express4.0
版本以上,把命令工具分離出來到express-generator
了,須要另外安裝,npm install -g express-generator
,不然項目搭建會出問題滴。node
這個環境中,react是使用node安裝的,npm install react --save-dev
,因爲react 0.14版本把react拆分爲react
和react-dom
,所以還須要將react-dom安裝一下,npm install react-dom --save-dev
。
在文件中直接引用就能夠:react
var React = require('react'); var ReactDom = require('react-dom');
分離之後,react package
中包含React.createElement、createClass、Component, .PropTypes,Children
這些API,而react-dom
中包含ReactDOM.render、unmountComponentAtNode、findDOMNode
。
注意對應使用React
或ReactDOM
調用。
另注意,react聲明組件時,第一個字母必須大寫。jquery
npm install webpack --save-dev
html-loader、css-loader、style-loader、url-loader、jsx-loader、babel-loader等
,安裝方式npm install ***** --save-dev
,在安裝這些loader以前,須要先安裝file-loader
,在安裝babel-loader
以前,須要先安裝babel-core
。commonsPlugin、UglifyJsPlugin、ExtractTextPlugin、HtmlWebpackPlugin
等,ExtractTextPlugin、HtmlWebpackPlugin
須要先npm install安裝
,commonsPlugin、UglifyJsPlugin
爲webpack自帶,無需額外安裝。當項目是單頁面時,能夠直接寫死entry的入口文件,也能夠直接寫死打包出的html頁面的名稱和路徑,但當項目是多頁面時,把入口文件和html打包名稱路徑等寫死就很是麻煩了,這時能夠使用node模塊glob
。使用方式見下面demo~webpack
html頁面裏不須要手動引入js和css,這裏webpack配置了生成帶引用的html,會自動把所需引用加入到html中
因此一個簡單的html就像這樣,不須要寫<link>
和<script>
標籤es6
貼一個webpack.config.js
的demo~web
/* 功能:打包文件,提取公共部分,並生成帶js\css引用的html頁面 打包前的文件,靜態資源放在public/src下,html在views下 打包後統一放在public/dist裏 使用的node模塊:path、glob 使用的webpack插件:commonsPlugin ExtractTextPlugin HtmlWebpackPlugin 網上有說開啓webpack觀察者模式會致使內存佔用太高,能夠用gulp調用webpack的方式解決 可是貌似這個項目並無這種問題~ */ /**************************引入webpack***********************************/ var webpack = require('webpack'); /**************************引入node模塊path、glob*******************************/ var path = require('path'); //該模塊用於返回匹配指定模式的文件名或目錄, //因爲本項目爲多頁面,所以須要多個入口文件和多個html //須要這個模塊獲取文件放入數組,須要時循環 var glob = require('glob'); /****************************設置默認路徑*******************************/ /* 設置默認路徑distPath,在module.exports中的output的path處使用 全部打包出的文件,路徑都在這個基礎上繼續 寫在這裏是由於比較突出。。直接寫在output的path固然也是能夠的 */ var distPath = path.join(__dirname,'/public/dist/'); /*****************************聲明getEntry函數**************************/ /* 該函數使用glob的方法,拆分文件路徑 目前有兩個地方使用了這個方法: 1. 循環view文件夾,生成多個html打包的conf配置; 2. 循環js入口文件 因爲module.exprots中的entry項是個對象,所以這裏把entry設爲{} 參數url爲傳進來的須要獲取的文件目錄的路徑 最後返回的entry的格式: { login : './public/src/js/Entry/user/login.js', register : './public/src/js/Entry/user/register.js' ******* } 在本身的實際項目中,按實際狀況能夠有其餘處理方式~ */ var getEntry = function (url) { var entry = {}; glob.sync(url).forEach(function (name) { /* 循環全部文件,對文件名作處理,並放入entry數組中,返回entry */ if(name.indexOf('views') != -1){ //是html頁面 var n = name.substring(8,name.lastIndexOf('.')); }else{ //不是html頁面 這裏實際上只有js頁面須要處理 var n = name.substring((name.lastIndexOf('/') + 1),name.lastIndexOf('.')); } var name = __dirname + name.substring(1); if(n.indexOf('.') != 0){ entry[n] = name; } }); return entry; }; /******************************使用webpack的插件********************************/ /* commonsPlugin,把公共部分提取出來 */ var commonsPlugin = new webpack.optimize.CommonsChunkPlugin({ // 提取出的公共模塊的名稱,js會打包爲common.js,css爲common.css // common.js會按照module.exports中output的路徑打包, // common.css會按照ExtractTextPlugin插件設置的路徑打包 //若是按照網上的例子直接寫爲common.js, //會致使提取出來的公共css被打包成css/js/common.js/css name: 'common', //chunks----從哪些文件中提取 //目前這裏不須要設置,由於全部js文件都須要被提取 //chunks: getEntry('./public/src/js/Entry/*/**.js') }); /* ExtractTextPlugin,打出單獨的css包 */ var ExtractTextPlugin = require("extract-text-webpack-plugin"); /* HtmlWebpackPlugin,打包html */ var HtmlWebpackPlugin = require('html-webpack-plugin'); /***********************設置module.exports中的plugins***************************/ /* 定義一個數組,module.exports中的plugins項能夠直接使用這個數組 */ var plugins = []; /* 添加打包公共文件插件的調用 */ plugins.push(commonsPlugin); /* 調用ExtractTextPlugin,把單獨的css打到dist/css/下面,該路徑也是從distPath開始 [name]爲引用這個css文件的js文件的入口文件打包後的名字,即入口文件output後的名字 */ plugins.push(new ExtractTextPlugin("css/[name].css")); /* 加載jq,不然項目中使用jquery會報錯'$ is not defined', 用jquery('#**')這樣的方式使用jquery固然也是不行滴~ */ plugins.push(new webpack.ProvidePlugin({ $: 'jquery' })); /**********************獲取全部html文件,生成HtmlWebpackPlugin插件須要的conf配置**************************/ /* 調用getEntry,傳遞路徑爲打包前的html文件 */ var pages = getEntry('./views/*/**'); /*循環pages*/ for(var chunkname in pages){ /* 這裏使用webpack的HtmlWebpackPlugin插件 conf爲該插件的配置項 將每一個文件的conf循環插入plugins,能夠實現多頁面打包 */ var conf = { filename: 'html/'+chunkname+'.html', //打包後的html存放路徑,也是從distPath開始 template: pages[chunkname], //文件模板,就是打包前的html文件 inject: true, //能夠對head和body作修改 //設置該頁面引用的文件,只有符合條件的纔會被引用 //這裏是'common'和頁面同名的js\css文件 chunks : ['jquery','react','react-dom','common', chunkname.substring(chunkname.indexOf('/')+1)], minify: { //壓縮HTML removeComments: true, collapseWhitespace: false }, hash: true, //版本號,打出來的html中對css和js的引用自帶版本號 } //把每一個conf循環插入plugins plugins.push(new HtmlWebpackPlugin(conf)); } /****************************添加對js和css的壓縮*************************/ plugins.push(new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, except: ['$', 'require'] //排除關鍵字,否則會把這些都壓縮替換 }) ) /**********************module.exports的entry配置*******************************/ //獲取全部入口文件 var entryJS = getEntry('./public/src/js/Entry/*/**.js'); /* 把react\react-dom-jquery單獨打包,若是不寫的話,會把這些都打到common.js裏 能夠解決common.js體積過大的問題~ */ entryJS['react'] = ['react']; entryJS['react-dom'] = ['react-dom']; entryJS['jquery'] = ['jquery']; /****************************webpack的整體配置******************************/ module.exports = { //入口文件,這裏循環全部入口文件,不須要每一個都寫出來 entry: entryJS, output: { //打包文件存放的絕對路徑,html、css、js都會按這個路徑打包 path: distPath, //網站運行時的訪問路徑,不設置的話,打包出的html中的默認引用的路徑會是相對路徑 publicPath: "/public/dist/", //打包後的文件名 filename: 'js/[name].js' }, resolve: { //require文件的時候不須要寫後綴了,能夠自動補全 extensions: ['', '.js', '.jsx','.css'] }, module: { loaders: [//定義一系列加載器 {test: /\.html$/,loader: "html"}, /*html*/ {test: /\.js$/, loader: "babel"}, /*es6 to es5*/ {test: /\.jsx$/,loader: 'jsx-loader'}, /*jsx to js,es5 to es6*/ {test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader")}, /*css to css*/ {test: /\.(jpg|png)$/, loader: "url?limit=8192"}, //limit=8192表示圖片大小單位是k 小於這個值走內聯大於這個值走外聯 /*images 打包*/ {test: /\.less$/, loader: "style!css!less"} /*less to css*/ ] }, plugins: plugins , //使用插件 //watch: true //開啓觀察者模式 };
未添加的功能:
圖片打包,按需加載,react熱替換
後面陸續加上~express