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