之前我们了解了webpack中的配置方式,下面我们来说一下实际生产中经常使用的loader以及plugin
以下说到的所有依赖都将省略安装过程,除非特别指明,否则都是直接npm安装依赖名
babel
虽然目前部分浏览器和 Node.js 已经支持 ES6,但由于它们对 ES6 所有的标准支持不全,这导致在开发中不敢全面地使用 ES6,babel 是一个 JavaScript 编译器,能将 ES6 代码转为 ES5 代码,可以很方便地完成这件事。
接入babel
babel引入方式很简单,通过loader的方式来引入
module.exports = { module: { rules: [ { test: /\.js$/, use: ['babel-loader'], },{ // 这里注意,如果eslint(语法检查工具)和babel同时使用 // eslint要优先执行,否则就是检查编译之后的代码了 // eslint也有自己的配置文件 .eslintrc,但是文件配置过长就不在这贴了,可以自行百度 test: /\.js$/, use: ['eslint-loader'], enforce: 'pre' } ] }, // 输出 source-map 方便直接调试 ES6 源码 devtool: 'source-map' }; 复制代码
babel配置
babel的引入方式很简单,单它还有自己的配置方式,你可能会在有些项目中看到。babelrc
这样的一个文件,他就是babel的配置文件,是一个json格式的文件,格式如下
{ "plugins": [ [ "transform-runtime", { "polyfill": false } ] ], "presets": [ [ "es2015", { "modules": false } ], "stage-2", "react" ] } 复制代码
plugins
属性告诉 Babel 要使用哪些插件,插件可以控制如何转换代码。以上配置文件里的 transform-runtime
对应的插件全名叫做 babel-plugin-transform-runtime
,即在前面加上了 babel-plugin-
,要让 Babel 正常运行我们必须先安装它
npm install -D babel-plugin-transform-runtime 复制代码
babel-plugin-transform-runtime的作用是减少冗余代码,比如在将ES6转换为ES5时,class extends语法将转为prototype语法,在编译时会注入_extends
辅助函数,会导致每个使用了 class extends 语法的文件都被注入重复的_extent
辅助函数代码,babel-plugin-transform-runtime会将注入的辅助函数替换为导入语句
var _extent = require('babel-runtime/helpers/_extent'); 复制代码
所以你还需要安装babel-runtime,用一条导入语句来替换一段代码,可以减少文件空间
presets
属性告诉 Babel 要转换的源码使用了哪些新的语法特性,一个 Presets 对一组新语法特性提供支持,多个 Presets 可以叠加。
更多babel详细配置可以参见官网
css预处理器
引入预处理器
适用于处理器可以大大加快开发速度,现在市面上常见的预处理器有scss、less、sylus等,他们的使用方法不再多说,想看的可以点链接去我之前的,以less为例
module: { rules: [ { test: /\.less$/, use: ['style-loader', 'css-loader', 'less.loader'] } ] } 复制代码
这里顺序不可以乱掉,按照从右往左的执行顺序,首先使用less-loader将less解析为css,然后使用css-loader找出 css代码中的 @import
和 url()
这样的导入语句,告诉 Webpack 依赖这些资源,style-loader 会把 CSS 代码转换成字符串后,注入到 JavaScript 代码中去,通过 JavaScript 去给 DOM 增加样式,注意:less-loader依赖less,在安装less-loader的时候同时要安装less
如果你不想将样式都以嵌入的形式插到html中,可以利用插件来分离css,之前用的是ExtractTextPlugin,但是现在使用的是MiniCssExtractPlugin,很多老教程中使用ExtractTextPlugin会出现问题,只要切换为MiniCssExtractPlugin即可。
分离单独css
style-loader负责将样式嵌入html中,既然我们想分离css,那就需要用MiniCssExtractPlugin提供的loader去处理样式
module: { rules: [ { test: /\.less$/, use : [ MiniCssExtractPlugin.loader, 'css-loader', 'less.loader' ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "css/style.css" }), ] 复制代码
自动兼容浏览器
对于前端er来说要兼容不同浏览器平台也是一件很头疼的事情,好在有postcss可以帮我们自动化兼容不同的浏览器
module: { rules: [ { test: /\.less$/, use : [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less.loader' ] } ] }, 复制代码
postcss在运行时会自动寻找.postcssrc文件,plugins 对象被指定为 key,并使用对象的值定义选项
{ "modules": true, "plugins": { "autoprefixer": { "grid": true } } } 复制代码
使用的插件需要单独安装
还可以在package.json中配置浏览器列表
"browserslist": [ "defaults", "not ie < 11", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ], 复制代码
想了解更多可以看这篇知乎
处理图片
base64
图片也是前端经常打交道的东西,几乎每个页面都有图片元素,处理图片元素我们可以使用url-loader来将图片转为base64,超出限制之后再使用file-loader,file-loader可以把 JavaScript 和 CSS 中导入图片的语句替换成正确的地址,并同时把文件输出到对应的位置。
module: { rules: [ { test: /\.(gif|png|jpe?g|svg|webp)$/, use: [{ loader: 'url-loader', options: { // 30KB 以下的文件采用 url-loader limit: 1024 * 30, // 否则采用 file-loader fallback: 'file-loader', } }] } ] }, 复制代码
压缩图片
此外还可以使用 image-webpack-loader 来压缩图片
module: { rules: [ { test: /\.(gif|png|jpe?g|svg|webp)$/, use: [{ loader: 'url-loader', options: { // 30KB 以下的文件采用 url-loader limit: 1024 * 30, // 否则采用 file-loader fallback: 'file-loader', } }, { loader: 'image-webpack-loader', options: { mozjpeg: { // 压缩 jpeg 的配置 progressive: true, quality: 65 }, optipng: { // 使用 imagemin-optipng 压缩 png,enable: false 为关闭 enabled: false, }, pngquant: { // 使用 imagemin-pngquant 压缩 png quality: '65-90', speed: 4 }, gifsicle: { // 压缩 gif 的配置 interlaced: false, }, webp: { // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式 quality: 75 } } }] } ] }, 复制代码
雪碧图
如果你的页面中含有很多icon小图标,可以采用雪碧图(CSS Sprites)的形式配合css的背景定位来较少图片加载,但是雪碧图 后期不好维护,每次新增图标都需要重新制作,那么有没有“偷懒的方法”,有!!!webpack是“万能的”,SpritesmithPlugin可以帮我们来完成这件事
resolve: { modules: [ 'node_modules', 'assets/sprite' //css在哪里能找到sprite图 ] }, plugins: [ new SpritesmithPlugin({ src: { cwd: path.resolve(__dirname, 'src/ico'), //准备合并成sprit的图片存放文件夹 glob: '*.png' //哪类图片 }, target: { image: path.resolve(__dirname, 'src/assets/sprites.png'), // sprite图片保存路径 css: path.resolve(__dirname, 'src/assets/_sprites.scss') // 生成的sass保存在哪里 }, apiOptions: { cssImageRef: "~sprite.png" //css根据该指引找到sprite图 } }) ] 复制代码
然后就可以在项目中使用了
@import './assets/sprite/_sprite.scss'; .open-icon{ @include sprite($open); } 复制代码
雪碧图形式和base64使用场景区别:建议在小图标特别多的时候使用雪碧图,图标数量少就还是使用base64吧
HTML模板
可以使用 html-webpack-plugin 插件来生成html文件,编译之后的依赖文件会自动注入
plugins: [ new HtmlWebpackPlugin({ template: 'assets/index.html', // 配置文件模板 }), ],