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路由,自己看例子吧
posted @ 2016-12-06 17:14  高桥名人救生圈  阅读(119)  评论(0)    收藏  举报