什么是loader?
webpack只能打包js模块,其他模块的打包需要借助loader。loader可以处理各种各样文件类型。
- file-loader:将文件处理后移动到打包文件中
- url-loader:可以实现file-loader的功能,而且可以限制文件限制,在文件比较小的情况下,可以返回一个DataURL,也可以打包字体。file-loader和url-loader,优先使用url-loader
{
test: /\.(png|jpe?g|gif)$/i,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images',
limit: 10240 // 小文件会打包成base64放到文件中,减少文件请求
}
}
}
- style-loader,css-loader,postcss-loader:打包css文件
- style-loader:将样式挂在在head里
- css-loader:生成css内容
- postcss-loader:css3新特性加厂商前缀
{
test: /\.scss$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
// modules:true, // css模块化,两个文件的样式不会耦合,使样式独立
importLoaders: 2 // 在该loader之前用2个loader处理import的资源
}
},
'sass-loader', // 翻译scss文件
'postcss-loader',
]
}
什么是plugins
plugins插件是 webpack 的支柱功能,可以解决 loader 无法实现的其他事。
- html-webpack-plugin:会在打包结束后,自动生成一个html文件,并把打包生成的js文件自动引入到这个html中,打包之后运行
- clean-webpack-plugin:打包之前运行,默认移除webpack的output中的所有文件
- 使用方法
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {
CleanWebpackPlugin
} = require('clean-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({ // 自动生成html文件
template: 'src/index.html'
}),
new CleanWebpackPlugin(), // 清空上次打包文件
],
}
source-map的配置
SourceMap是映射关系,可以知道打包出的文件报错位置映射到源文件中的哪个文件的具体位置,开发环境与实际代码不一致时可以帮助我们debug到原始代码。
- development环境可以配置为
devtool: 'cheap-module-eval-source-map', // 开发环境配置
- production环境可以配置为
devtool: 'cheap-module-source-map', // 生产环境配置
- 配置介绍
- eval:使用eval包裹模块代码,然后在末尾添加模块来源 //# sourceURL,依靠sourceURL找到原始代码的位置。包含eval关键字的配置项不产生.map文件(eval依靠sourceURL定位原始代码,其他都是.map定位)—性能最好
- source-map:产生.map文件 — 性能最低
- cheap:不包含原始代码的列信息,也就是说当你在浏览器中点击该代码的位置,光标只定位到行数,而不包含具体字符位置。也不包含loaders的sourcemap,如果你使用了babel等代码编译工具,定位到的代码将是经过编译的代码位置,而不是原始代码
- module:包含loader的sourcemap
- inline:将.map经过base64编码作为DataURI嵌入,不单独生成.map文件
WebppackDevServer和Hot Module Replacement(HMR)
WebppackDevServer:用在开发环境,提升开发效率;HRM:开发过程中,无需重新加载整个页面,去更新各种模块。
- 配置WebppackDevServer
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true, // 开启HMR的功能
hotOnly:true // HMR不生效时,浏览器不自动刷新
},
- 引入插件
const webpack = require('webpack');
plugins: [
new webpack.HotModuleReplacementPlugin()
]
- 使用
在入口文件中加入以下代码:如果当前项目开启了HMR的功能,支持Hot module reload,js需要写这段代码才能实现热更新。css不需要写,是因为css-loader底层已经实现了热更新。vue-loader也内置了这部分。但是如果在项目中引入了一些比较偏的数据类文件,还是要写这部分代码。
if(module.hot) {
module.hot.accept('./number',() => {
document.body.removeChild(document.getElementById('number'));
number();
})
}
使用babel处理es6语法
- 安装
npm install --save-dev babel-loader @babel/core
- 在webpack.config.js中使用
babel-loader是webpack与babel通信的桥梁,并不会翻译es6语法,还需要借助其他模块,@babel/preset-env包含了所有es6转换成es5的翻译规则语法转换
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
}
- 安装preset-env
npm install @babel/preset-env --save-dev
- 使用
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: [
['@babel/preset-env', {
targets: {
chrome: '76'
},
useBuiltIns: 'usage' // 当做babel-polyfill填充时,根据业务代码决定加哪些翻译代码
}]
]
}
}
- 引入babel-polyfill
将babel-presets缺失的变量和函数补充到低版本浏览器中。如果放到业务代码最顶部的入口文件中,打包时会将不需要的文件打到文件中,导致打包文件大小变大,所以配置useBuiltIns可以做到按需引入polyfill的内容。
import "@babel/polyfill";
以上方式引入polyfill会污染全局环境。如果是写一些UI组件或者类库,不能用这种引入方法。可以用下面这种方式配置:
- 安装@babel/plugin-transform-runtime
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
- 使用
'plugins': [
['@babel/plugin-transform-runtime', {
'corejs': 2, // npm install --save @babel/runtime-corejs2
'helpers': true,
'regenerator': true,
'useESModules': false
}]
]
以上是最近学习webpack的一些成果,如果有不对的,欢迎大家指正哦~