主要在实战上,可能对于概念讲解上不太多,如果有需要的同学可以自己看下官方文档
webpack2发布也有了大半年,最近也刚开始接触webpack2的升级工作,从webpack1开始我就没有好好耍,突然一下子弄webpack2还是有点小小的激动的,废话不多说开始讲下我升级的一些方法和技巧。
我们首先需要看官网上推荐的升级文档,这里很详细的介绍了Migrating,但我觉得这文档还有好多地方需要补充的,也是后来结合实际的开发中所遇到的问题。
接下来我先讲下webpack大体的结构,因为有些同学可能对webpack还不太了解,有entry,output,loaders,plugins,大体一个配置文件由4个部分组成,接下来我就会从这4个部分来展开分享,我会以每块区域先讲概念,然后会留下一些问题的方式给大家,最后再来解答的形式来讲解。
接下来的要打起精神哟!
因为实在挺重要的 > ^_^ <
因为实在挺重要的 > ^_^ <
因为实在挺重要的 > ^_^ <
重要的说三遍
Entry
它就是一个入口文件,也就是告诉webpack该从哪个文件着手去解析,然后entry的配置一般常用的就是多入口
entry: {home: "./home.js",about: "./about.js",contact: "./contact.js",vendor: ['react','react-dom']}
上面就代表了三个入口,分别是Home,About,Contact,分别对应三个js,一般入口可以对应路由组件里的map,其次还有一种情况是针对于第三方的vendor处理,将第三方的lib打包在vendor里,这里会涉及到一个内容叫Code Split,后面我会讲到,大家可以先简单理解成这块的处理就是为了将第三方的lib放一起,利用浏览器缓存来缓存文件。
Output
既然前面提到了输入,那肯定会有对应的输出,这里output就是对应的输出属性。
output: {path: '/home/proj/public/assets',publicPath: '//cdn.com',filename: 'js/[name]-[chunkhash:8].js'chunkFilename: 'js/[name]-[chunkhash:8].js',}
path 代表的就是文件给输出的目录,publicPath 代表的就是上线后cdn所对应的路径,filename 代表的就是输出的文件名字,由name 和 chunkhash 前8位组成,chunkFilename 代表的就是 chunk 出来的名字。
Loaders
Loaders就是加载器,它主要的作用的处理静态文件的,你可以想象成流水线上不同的商品的处理机器,它会流程化的去处理这些文件
module: {rules: [*****loaders,*****loaders*****]}
常用的loaders:
eslint-loader
{enforce: "pre",test: /\.(js|jsx)$/,loader: "eslint",include: [path.resolve(CWD, config.base)],exclude: /node_modules/,options: {configFile: path.resolve(CWD, '.eslintrc'),}}
eslint 是需要enforce: "pre" 为preLoader(webpack1) 就是预加载器,可以在编译前对代码进行eslint检测
babel-loader
{test: /\.jsx?$/, // .jsx or .js filesloader: 'babel',query: require('./babel.prod'),exclude: /node_modules/,include: CWD},
主要是对js或者jsx语法进行编译,一般是将es6转为 es5,可以通过query方式传递babel config, 然后exclude, include来执行对应的模块。
这里值得注意注意注意的是query的这种传参方式可以让我们灵活去处理dev与pro环境下的babel编译处理,另外,如果你的开发环境是chrome等现代浏览器,原生就已经支持ES6的大部分特性,就可以在开发时去掉大部分的preset和plugin,只保留babel-preset-react等浏览器无法支持的预设,以提升编译速度,上线时再加上剩余的babel转换。
css-loader
less-loader
sass-loader
这三个loader主要是处理样式的,这里我就结合我们的项目讲下sass-loader
{test: /\.scss$/,exclude: [path.resolve(CWD, config.base, config.scss)],// pack other styles into JS and wrapped within style at runtimeuse: ['style',{loader: 'css',options: config.css_modules ? {modules: true,importLoaders: 1,localIdentName: '[name]__[local]__[hash:base64:8]',}: {},},'postcss','resolve-url',{loader: 'sass',options: {sourceMap: true,includePaths: [path.resolve(CWD, 'node_modules'), path.resolve(CWD, config.base)]}}]}
这个配置比较全,也比较长,我会一一讲解的。
首先这里需要注意的是use:[] 这种写法,这其实是chainsLoader, 在webpack1 和 webpack2 写法上是不同的,这里有对应的文档参考,然后可以看到 use 这个数组里有 style-loader,css-loader,postcss-loader,resolve-url-loader,sass-loader。
style-loader:主要做的事情就是帮你去内敛css到页面里。
css-loader: 这里可以看到我们有个config.css_modules的一个配置项,作用就是是否开启css modules的语法糖,不了解css modules的同学可以自己google下,然后在css-loader里可以看到三个参数,第一个是modules代表是否开启,第二个参数importLoader可以先过我后面会讲,第三个参数localIdentName就是css modules后标签对应的规则。
postcss-loader: 在这里我们postcss-loader主要的作用是autoprefixer, 加浏览器前缀兼容各种版本的浏览器。
resolve-url-loader: 这里其实配合sass-loader来使用的,当使用sass-loader的时候需要使用resolve-url-loader来找到对应的url资源。
sass-loader: sass的加载器,处理sass的,这里的参数sourceMap非常重要,切忌不要掉了,不然你的图片对应的路径是无法编译出来的,以前我们在处理图片的时候可能是这样处理的 ~assets/images/test.png , 利用 ~ 处理绝对路径,然后现在有sourceMap后,你可以去处理相对路径的图片,这种相对路径就需要与你的 resolve 这个属性下的root 来匹配,resolve 后面我会好好讲讲,现在你只需要记着图片也可以通过相对路径处理。
svg-loaderhttps://github.com/SamHerbert/SVG-Loaders
url-loaderhttps://github.com/webpack-contrib/url-loader
file-loaderhttps://github.com/webpack-contrib/file-loader
json-loaderhttps://github.com/webpack-contrib/json-loader
这些loader 比较简单所以贴了github地址大家可以自己去学习。
常用的Loader就是这些了,提完loader,不得不讲下跟loader相关的一个东西,那就是 resolveLoader属性
resolveLoader: {modules: [path.resolve(__dirname, '..', '..', 'node_modules'),],/*** Automatic -loader module name extension removed* https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed*/moduleExtensions: ["-loader"]},
第一个参数是modules,主要是针对loader的引用路径,第二个参数则是可以省略loader的写法的,上面的loader,我都没在后面写*-loader , 就是因为加了这个东西,如果不加的话你就得写全不然就报错了~~~。
Plugins
常用插件
插件名功能
HotModuleReplacementPlugin模块热替换用的,主要是在dev环境下
DefinePlugin定义一些变量,在编译的时候会把这些变量给编译成定义的值
CommonsChunkPlugin主要是为了合并公共chunk的插件
ProvidePlugin定义一个变量让你能在代码里使用,但全局无法访问,比如jquery
UglifyJsPlugin压缩和混淆代码用的
ExtractTextPlugin主要是为了抽离css合并成一个文件
HtmlWebpackPlugin模板生成引擎,语法类似artTemplate
LoaderOptionsPlugin让webpack2结构更加严谨,避免webpack1中的自定义插件,尽量使用options来传递参数
Question:
1. 为什么vendor要用数组写,这样写是什么意思?2. 官网上提供了 id,name,hash,chunkhash , 为什么要这样写,这样写有什么好处,它们的区别是什么?3. postcss-loader 为什么不处理变量逻辑?4. importLoader 到底是做什么用的?5. use 里的 loader 顺序能随便写吗?
答案我会在后期补充~^_^