webpack学习笔记
一、入口文件
所谓入口文件,就是webpack通过你写的js根据种种依赖关系生成的页面上可以直接使用的js,这样就免去了引用一大堆js的问题?比如我现在为页面上写的js叫main.js,然后我想要引用的话就不能在html里直接引用这个js了,需要在webpack.config.js声明,生成一个bundle.js,意思就是捆,就是把相关联的js全都捆绑在一起,这样比较省事,好管理吧~
1 // webpack.config.js 2 module.exports = { 3 entry: './main.js', 4 output: { 5 filename: 'bundle.js' 6 } 7 };
二、多个入口文件
为啥会有多个入口文件?据说多个页面会用到,比如说我们做的点菜app分为首页+点菜页+确认页+支付页等等好多页面,这些个页面都有自己的js文件,那打包的时候怎么打呢 ?很简单 webpack.config.js这么着写就对了:
1 module.exports = { 2 entry: { 3 bundle1: './main1.js', 4 bundle2: './main2.js' 5 }, 6 output: { 7 filename: '[name].js' 8 } 9 };
其中[name]就表示打包的entry的名字,也就是bundle1、2什么的啦,最后会生成bundle1.js、bundle2.js,然后在画面上引用就可以啦~
三、Babel-loader
Babel-loader又是个啥?就是个loader。loader就是一个类似编译器的东西吧?把那些个JSX啦ES6啦类似的东东都“编译” 成JS文件,否则你写的ES6语法谁知道是什么鬼
比如说,你想在你的工程里用react,所以你写了一堆jsx,想要程序正常运行那就得加loader了,样例给出的webpack.config.js是这个样子的:
1 module.exports = { 2 entry: './main.jsx', 3 output: { 4 filename: 'bundle.js' 5 }, 6 module: { 7 loaders:[ 8 { 9 test: /\.js[x]?$/, 10 exclude: /node_modules/, 11 loader: 'babel-loader?presets[]=es2015&presets[]=react' 12 }, 13 ] 14 } 15 };
明白人一看便知,相比之前的webpack.config.js,这里新增了module部分,其中Babel-loader就是这里面的loaders中的一种。你没看这里的loaders是个数组嘛?是数组就肯定会有其他loaders的,后面会讲。test属性就相当于过滤器吧?让webpack判断是什么扩展名的文件需要走这个loader?exclude属性表示loader的所处位置吧?一般貌似都是node_modules。loader表示当前是什么loader,这里它写的比较怪异。我们来看看张老师写的:
1 { 2 test:/\.jsx?$/,loader:"babel",exclude:/node_modules/, 3 query: 4 { 5 presets:["es2015", "stage-0", "react"] 6 } 7 },
看得出来写法上有些差异了吧?还是张老师这种写法比较简易明了,大家向他学习👏
那么问题来了,presets到底是个什么鬼?其实这个是babel6新加的,代表启动什么样的预设转码,告诉loader该怎么把你的ES2015啦、react啦全都转成可以运行的js。中间的stage-0其实包含了1~3,它包含了从1到3的所有功能,实际开发时可以根据需要设定不同的stage,不过一般开发谁会这么脑残还给自己挖坑?所以一般设个stage-0就可以啦。至于那个ES2015和react就是表示转码ES6和react用的,那就不多说了
四、CSS-loader
顾名思义,就是引用CSS文件的loader。有时候我们在js或者jsx里引用了CSS,就必须加入此loader,否则样式全都出不来?不明白为什么我在加入antd时写了loader也不会出现相应的样式,真是头疼😓
样例是这么写的:
1 loaders:[ 2 { test: /\.css$/, loader: 'style-loader!css-loader' }, 3 ]
1 { //引入sass 2 test:/\.scss/, 3 loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader"), 4 exclude:/node_modules/ 5 }, 6 { //引入less 7 test:/\.less/, 8 loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader") 9 }, 10 { //引入css 11 test:/\.css/, 12 //loaders: ["style","css"] 13 loader: ExtractTextPlugin.extract("style-loader", "css-loader") 14 }
看的出来张老师引用的三个样式的loader,其中有scss和less以及我们的css。sass和less都是css的预处理器,都有相同的功能,可以帮助我们快速的编译代码,帮助我们更好的维护我们的样式代码。但是网上说sass比less要好,比较成熟,以后可以研究研究学一学。
这里需要注意一下,想要正确的引用CSS文件,光靠加一个CSS-loader去读CSS文件是不行的,还得把你的CSS样式引导你所用样式的HTML文件里去。之前我在引用antd时就遇到了这个坑,config文件样式引用都没有错,但是就是页面上没法出现antd相应的样式来,最后豁然开朗,原来是HTML里没有引进生成的CSS文件!有关antd上的东西,找机会另说吧~
等等,这里有个问题,如果你的CSS文件和html里引用的css样式不一致怎么办?样例上是这个样子的,按说应该不能这么写,同一个样式为啥要写两边呢?后来看看github上的代码,原来还不是这样子,不过更奇特,居然只是在js里面引用了一下css,正式的html里竟然没有引用css,然后样式照样出来了,这究竟是怎么一回事呢?
原来默认的话他直接引用了css-loader,这样貌似webpack直接就把所用到的css打包到了html里了?具体原因不明。而张老师那个例子呢?他用了ExtractTextPlugin这个插件,可能就是将样式直接打包到了独立的一个css文件里去,这样的话html直接应用这个生成的css文件就可以了。总的来说,还是张老师的方法好!
五、Image loader
顾名思义,就是加载图片的loader。在现在网站中,图片是缺少不了的,里面有大图有小图,要是大图也就罢了,净是一堆小图,每次读小图都是一次http请求,很浪费网络的,所以……哐哐哐,Image loader应运而生。
Image loader的config文件是这么写的:
1 { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
等等……url-loader?不是Image loader嘛?框我?实际上在运行时还会提示我安装file-loader这个插件。经查明,原来url-loader和file-loader都是用来加载图片用的,区别在于url-loader是对file-loader的上层封装,样例中的加载器配置表明,小于8k的图片讲直接以base64的形式内联在代码中,可以减少一次http请求,yeah~
至于怎么引图片?直接在js里引用图片文件名即可~
六、CSS Module
参照我上面写cssloader时遇到的问题。其实antd就相当于一个css module吧?必须得在html里引用css文件,整个工程才能够可以维护,否则把css样式直接生成在html里,要改点儿什么改怎么改啊,头都大了!
七、UglifyJs Plugin
一言以蔽之,这个插件就是拿来缩短代码量的。把你写的好几千行的js给缩成几行呵呵~
需要的是,此时就需要在config文件中声明一下这个插件的变量了,同事在插件那块儿写明参数,具体参数请上网查
八、HTML Webpack Plugin and Open Browser WebpackPlugin
这个demo就是为了教你怎么引用第三方插件。HTML Webpack Plugin是用来创建index.html文件的,Open Browser WebpackPlugin是用来自动打开浏览器的,是不是很高端?
直接看他的config文件怎么写:
1 var HtmlwebpackPlugin = require('html-webpack-plugin'); 2 var OpenBrowserPlugin = require('open-browser-webpack-plugin'); 3 4 module.exports = { 5 entry: './main.js', 6 output: { 7 filename: 'bundle.js' 8 }, 9 plugins: [ 10 new HtmlwebpackPlugin({ 11 title: 'Webpack-demos', 12 filename: 'index.html' 13 }), 14 new OpenBrowserPlugin({ 15 url: 'http://localhost:8080' 16 }) 17 ] 18 };
可以看出来,他在config直接应用了插件名字(前提是你必须npm install安装完毕),然后在plugins里对插件进行相应的配置即可,比如这里的首页名标题什么的,具体参数是嘛请参阅网上相应资料吧~
九、Environment flags
这个就是表示你可以设定一些代码是开发者模式才能够启用的,比如说一些不能说的秘密,一些乱七八糟的console,一些low到爆的alert等等。那具体怎么实现呢?
看作者的实例,首先貌似声明一个全局变量_DEV_,然后在所有不改有的代码中套上这个变量的if,然后在config文件中这么写:
1 var devFlagPlugin = new webpack.DefinePlugin({ 2 __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false')) 3 }); 4 5 module.exports = { 6 entry: './main.js', 7 output: { 8 filename: 'bundle.js' 9 }, 10 plugins: [devFlagPlugin] 11 };
可以看出来,他实际上是引用了一个叫DefinePlugin的插件,congfig文件的意思就是开始运行的时候从环境变量里读取DEBUG信息。那么怎么设置环境变量呢?参照下文:
1 # Linux & Mac 2 $ env DEBUG=true webpack-dev-server 3 4 # Windows 5 $ set DEBUG=true 6 $ webpack-dev-server
十、Code Splitting
这个是重头戏,里面貌似 水很深,参照这篇文章: http://www.cnblogs.com/E-WALKER/p/4770063.html
这里就涉及到了AMD和CommonJS这两个标准了,两种标准调用方式不同,处理结果也不同,具体哪里不同请参看上面那篇文章。
样例给的代码应该是CommonJS标准的:
1 // main.js 2 require.ensure(['./a'], function(require) { 3 var content = require('./a'); 4 document.open(); 5 document.write('<h1>' + content + '</h1>'); 6 document.close(); 7 }); 8 // a.js 9 module.exports = 'Hello World';
也就是说a.js作为一个模块,输入了"Hello World"这个字符串,然后webpack在打包时,确保ensure 参数数组里的所有模块全都加载完毕后才会执行回调函数,ensure所起的作用仅仅是加载组件,不会执行代码,若要执行,则需要借助传进去的require参数。比如说样例,在运行时可以看出来不光生成了一个bundle.js文件,还生成了一个1.bundle.js文件,至于那个1是怎么出来的我也不知道啊。运行时看浏览器可以清楚的看到它先加载了bundle.js而后又通过bundle.js加载了1.bundle.js
十一、Code splitting with bundle-loader
也是一种 Code splitting的方法,样例如下:
1 // main.js 2 3 // Now a.js is requested, it will be bundled into another file 4 var load = require('bundle-loader!./a.js'); 5 6 // To wait until a.js is available (and get the exports) 7 // you need to async wait for it. 8 load(function(file) { 9 document.open(); 10 document.write('<h1>' + file + '</h1>'); 11 document.close(); 12 });
没啥可说的,方法不同而已,看代码就能明白。
十二、十三、看不明白,也看不下去了
十四、Exposing global variables
卧槽,全局变量?怎么用呢?先写一个data.js,里面是各种变量,然后在config文件里加点儿料:
1 // webpack.config.js 2 module.exports = { 3 entry: './main.jsx', 4 output: { 5 filename: 'bundle.js' 6 }, 7 module: { 8 loaders:[ 9 { 10 test: /\.js[x]?$/, 11 exclude: /node_modules/, 12 loader: 'babel-loader', 13 query: { 14 presets: ['es2015', 'react'] 15 } 16 }, 17 ] 18 }, 19 externals: { 20 // require('data') is external and available 21 // on the global var data 22 'data': 'data' 23 } 24 };
对,就是externals那部分。然后呢?data就是去全局变量了么?答案是肯定的。
十五、Hot Module Replacement
模块热替换?听上去挺酷,但是感觉没啥用,而且webpack-dev-server本身不就有这功能么?求解
十六、React router
React路由,自己看例子吧

浙公网安备 33010602011771号