目录
style-loader、less-loader、sass-loader、css-loader、postcss-loader
一、什么叫webpack
当下最热门的前端资源模块化管理工具,可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源;
可以理解为是一个js应用程序的静态模块打包器,它会递归的构建一个依赖关系图,其中会包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle(包);
二、webpack核心
- entry:入口
- loader:模块转换器,用于把模块原内容按照需求转换成新内容
- plugins:扩展插件,在webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要做的事情
- output:输出
三、entry入口
入口的字段为: entry
module.exports = { entry: './src/index.js' //webpack的默认配置 }
entry 的值可以是一个字符串,一个数组或是一个对象。
字符串的情况无需多说,就是以对应的文件为入口。
为数组时,表示有“多个主入口”,想要多个依赖文件一起注入时,会这样配置。例如:
module.exports = { entry: [ './src/polyfills.js', './src/index.js' ] }
polyfills.js 文件中可能只是简单的引入了一些 polyfill,例如 babel-polyfill,whatwg-fetch 等,需要在最前面被引入。
四、output输出
配置 output 选项可以控制 webpack 如何输出编译文件。
const path = require('path'); module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), //必须是绝对路径 filename: 'bundle.js', publicPath: '/' //通常是CDN地址 } }
例如,你最终编译出来的代码部署在 CDN 上,资源的地址为: ‘https://AAA/BBB/YourProject/XXX’,那么可以将生产的 publicPath 配置为: //AAA/BBB/。
编译时,可以不配置,或者配置为 /。可以在我们之前提及的 config.js 中指定 publicPath(config.js 中区分了 dev 和 public), 当然还可以区分不同的环境指定配置文件来设置,或者是根据 isDev 字段来设置。
除此之外呢,考虑到CDN缓存的问题,我们一般会给文件名加上 hash.
module.exports = { output: { path: path.resolve(__dirname, 'dist'), //必须是绝对路径 filename: 'bundle.[hash].js', publicPath: '/' //通常是CDN地址 } }
如果你觉得 hash 串太长的话,还可以指定长度,例如 bundle.[hash:6].js
五、loader篇
loader作为webpack的核心之一,其工作就是将源代码转换
为啥要转换源代码呢?
- 有些低端的运行环境(node、浏览器)是无法识别并运行一些新的语法(例如es2015后的一些新语法);
- webpack不能直接处理css、less、sass这些样式文件;
- 对一些图片、字体这些本地文件做更好的处理;
因此我们要把源代码转成低版本的代码,向下兼容;
babel-loader
作为前端不知道何为babel就要好好反省反省了 -->什么是 Babel? · Babel 中文文档
安装依赖
安装 babel-loader
// 使用npm npm install babel-loader -D // 使用yarn yarn add babel-loader -D
安装babel相关配置依赖
// 使用npm npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -D npm install @babel/runtime @babel/runtime-corejs3 // 使用yarn yarn add @babel/core @babel/preset-env @babel/plugin-transform-runtime -D yarn add @babel/runtime @babel/runtime-corejs3
进行配置
babel-loader配置
webpack.config.js
文件中module.rules 是一个对象数组,里面可以放一个个配置规则
rules数组中每个对象又下面这几个配置:
- test:指定需要处理的对应文件
- exclude:指定不需要处理的对应文件
- use:他的值可以是字符串、也可以是对象(只有一种loader的时候我们可以使用对象)、也可以是数组(一般我们写成数组)
-
- 我们可以把babel的配置写在use里面;
- 也可以建一个
.babelrc
或babel.config.json
文件去进行配置(建议,不要什么都写package.json文件里面,显的文件太庞大)
//webpack.config.js module.exports = { module: { rules: [ { test: /\.jsx?$/, // 指定想要处理的对于文件 use: ['babel-loader'], exclude: /node_modules/ //排除 node_modules 目录 } ] } }
// .babelrc { "presets": ["@babel/preset-env"], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": 3 } ] ] }
style-loader、less-loader、sass-loader、css-loader、postcss-loader
webpack 不能直接处理 css,需要借助 loader。如果是 .css,我们需要的 loader 通常有: style-loader、css-loader,考虑到兼容性问题,还需要 postcss-loader,而如果是 less 或者是 sass 的话,还需要 less-loader 和 sass-loader,这里配置一下 less 和 css 文件(sass 的话,使用 sass-loader即可)
ps:postcss-loader中有一个插件autoprefixer是前端福音,他能帮我们去自动补全比如 CSS3 的前缀问题,解放我们的双手
例如
.box { border-radius: 10px; } // 经过autoprefixer这么一转他就帮我们加上了很多兼容代码,变成下面这个 .box { -moz-border-radius: 10px; -webkit-border-radius: 10px; -o-border-radius: 10px; border-radius: 10px; }
安装依赖
// 使用npm npm install style-loader less-loader css-loader postcss-loader autoprefixer less -D // 使用yarn yarn add style-loader less-loader css-loader postcss-loader autoprefixer less -D
进行配置
webpack.config.js
module.exports = { module: { rules: [ { test: /\.jsx?$/, use: ['babel-loader'], exclude: /node_modules/ //排除 node_modules 目录 }, { test: /\.(le|c)ss$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'], exclude: /node_modules/ } ], }, ... }
postcss.config.js
module.exports = { plugins: [ require('autoprefixer')({ "overrideBrowserslist": [ "defaults", "not ie < 11", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ] }) ] }
我们简单说一下上面的配置:
- style-loader 动态创建 style 标签,将 css 插入到 head 中.
- css-loader 负责处理 @import 等语句。
- postcss-loader 和 autoprefixer,自动生成浏览器兼容性前缀 ——2020了,应该没人去自己徒手去写浏览器前缀了吧
- less-loader 负责处理编译 .less 文件,将其转为 css
这里,我们之间在 webpack.config.js 写了 autoprefixer 需要兼容的浏览器,仅是为了方便展示。推荐在根目录下创建 .browserslistrc 或 postcss.config.js,将对应的规则写在此文件中,除了 autoprefixer 使用外,@babel/preset-env、stylelint、eslint-plugin-conmpat 等都可以共用。
url-loader、file-loader
在webpack 中 url-loader 或者 file-loader 来处理本地的资源文件。url-loader 和 file-loader 的功能类似,但是 url-loader 可以指定在文件大小小于指定的限制时,返回 DataURL,因此,个人会优先选择使用 url-loader。
安装依赖
// 使用npm npm install url-loader -D // 使用yarn yarn add url-loader -D
进行配置
module.exports = { //... modules: { rules: [ { test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/, use: [ { loader: 'url-loader', options: { limit: 10240, //10K esModule: false } } ], exclude: /node_modules/ } ] } }
此处设置 limit 的值大小为 10240,即资源大小小于 10K 时,将资源转换为 base64,超过 10K,将图片拷贝到 dist 目录。esModule 设置为 false,否则,<img src={require(‘XXX.jpg’)} /> 会出现 <img src=[Module Object] />
将资源转换为 base64 可以减少网络请求次数,但是 base64 数据较大,如果太多的资源是 base64,会导致加载变慢,因此设置 limit 值时,需要二者兼顾。
默认情况下,生成的文件的文件名就是文件内容的 MD5 哈希值并会保留所引用资源的原始扩展名。
六、webpack重要的一些plugin
html-webpage-plugin
作用
- 可以生成创建html文件入口,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口
- 可以根据我们在htmlWebpackPlugin的
config
的配置,在每次build中对html文件中动态的外部资源(例如根据不同环境引入不同的讲台资源)
对应安装与引入
安装
// 使用npm npm install html-webpack-plugin -D // 使用yarn yarn add html-webpack-plugin -D
引入
webpack.config.js 引入配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); const isDev = process.env.NODE_ENV === 'development'; const config = require('./public/config')[isDev ? 'dev' : 'prod']; module.exports = { module: { rules: [ { test: /\.jsx?$/, use: ['babel-loader'], exclude: /node_modules/ //排除 node_modules 目录 } ], }, mode: isDev ? 'development' : 'production', plugins: [ new HtmlWebpackPlugin({ template: './public/index.html', filename: 'index.html', //打包后的文件名 config: config }) ] }
此时./public/index.html文件就可以根据根据config配置在打包时进行动态加载静态资源
module.exports = { dev: { title: 'hello dev', isImportAxios: true }, prod: { title: 'hello prod', isImportAxios: false } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><%= (htmlWebpackPlugin.options.config.title) %></title> </head> <body> <% if(htmlWebpackPlugin.options.config.isImportAxios) { %> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <% } %> </body> </html>
对应配置属性说明
属性 | 对应值类型 | 备注 |
title | string | 生成html的页面标题 |
filename | string | 打包后的文件名,默认是index.html |
template | string(值是一个路径) | 主文件路径 |
favicon | string(值是一个路径) | 给你生成的html文件生成一个 favicon(页面图标) |
minify | object | boolean | 使用minify会对生成的html文件进行压缩,默认是false 可配置属性有: removeAttributeQuotes //是否删除属性的双引号 collapseWhitespace //是否折叠空白 |
hash | boolean | 是否加上hash,默认是 false |
。。。 |
webpack-dev-server
作用
webpack-dev-server是一个小型的Node.js Express本地服务器,处理打包资源与静态文件请求,live-reloading功能监听文件变化,自动化新页面提升开发效率;对于 webpack 来说几乎是标配;
工作原理
一般我们在开发环境,我们会在项目中运行启动webpack-dev-server本地服务器,例如yarn dev
当服务器启动后,会先让webpack进行模块打包并将资源准备好;
wepack 打包每次都会生成bundle.js,webpack-dev-server只是把打包结果放在内存中,每次接收到请求就将内存中的打包结果返回给浏览器;
webpack-dev-server还有一个很便捷的特性就是live-reloading(自动刷新)
引用与配置
引用
yarn add -D webpack-dev-server
运行脚本配置
{ "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server", "build": "cross-env NODE_ENV=production webpack" }, ... }
此时yarn dev
便可以在本地基于对应项目搭建一个本地服务器
devServer配置
此时在webpack.config.js的devServer
配置相关参数 就可以对本地服务器的配置进行调整
module.exports = { //... devServer: { port: '3000', //默认是8080 host: '0.0.0.0', //默认127.0.0.1,当然你也可以不写这里,再启动时带上 --host 0.0.0.0 也可以 headers: { //在HTTP响应中注入一些HTTP响应头 'X-test': 'test' }, // 正则匹配默认跳转到对应路由 historyApiFallback: { rewrites: [ { from: /^\/user/, to: '/user.html' }, { from: /^\/home/, to: '/home.html' } ] }, //该配置项是指模块替换换功能,DevServer 默认行为是在发现源代码被更新后通过自动刷新整个页面来做到实时预览的 //但是开启模块热替换功能后,它是通过在不刷新整个页面的情况下通过使用新模块替换旧模块来做到实时预览的 hot: true, open: true, //默认false,完成构建的时候,会自动打开默认的浏览器来查看网页 // 解决跨域的问题 proxy: { '/api': { target: 'http://my.api.com', // 目标接口的域名 // secure: true, // https 的时候 使用该参数 changeOrigin: true, // 是否跨域 pathRewrite: { '^/api' : '' // 重写路径 } } } } }
clean-webpack-plugin
作用
每次文件修改后,重新打包,导致 dist 目录下的文件越来越多。要是每次打包前,都先清空一下目录就好啦。于是clean-webpack-plugin来了,帮我们做到每次打包前先自动去清理dist目录
引用与配置
引用
// npm npm install clean-webpack-plugin -D // yarn yarn add clean-webpack-plugin -D
配置
//webpack.config.js module.exports = { //... plugins: [ new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns:['**/*', '!dll', '!dll/**'] //不删除dll目录下的文件 }) ] }
七、devtool
其作用主要是用开发调试,根据错误和调试信息及时去定位具体代码
官网的配置说明如下图
一般开发环境下要调试所以会选择下面这个模式:eval-cheap-module-source-map(个人认为),原因如下:
- 展示的是原始的源代码,更能一眼看到问题;
- 相对eval-source-map他构建会快一些,而且定位到对应的某一行已经够了,不需要具体到某一个位置;
一般生产环境不回去调试,或者说很少会去调试,因此会使用这几个模式:none(不配置,本人主推),hidden-source-map、source-map,考虑因素主要:
- 包的大小
- 构建的速度
- 不想太容易的暴露源码