前言日常开发者中,我们常常在用诸如vue-cli、create-react-app的脚手架来构建我们的项目。但是如果你想在团队脱颖而出(鹤立鸡群)、拿到更好的offer(还房贷),那么你必须去深刻的认识下我们经常打交道的webpack
1 入门(一起来用这些小例子让你熟悉webpack的配置)1.1 初始化项目新建一个目录,初始化npm 需要npm init webpack是运行在node环境中的,我们需要安装以下两个npm包 下包:pm i -D webpack webpack-cli - npm i -D 为npm install --save-dev的缩写
- npm i -S 为npm install --save的缩写
新建一个文件夹src ,然后新建一个文件main.js,写一点代码测试一下
console.log('这是测试的文字')
配置package.json命令
执行
需要在最外层的目录下进行npm run serve
此时如果生成了一个dist文件夹,并且内部含有main.js说明已经打包成功了
1.2 开始我们自己的配置上面一个简单的例子只是webpack自己默认的配置,下面我们要实现更加丰富的自定义配置
新建一个build文件夹,里面新建一个webpack.config.js
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
const path = require('path');
module.exports = {
mode:'development', // 开发模式
entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
output: {
filename: 'output.js', // 打包后的文件名称
path: path.resolve(__dirname,'../dist') // 打包后的目录
}
}
更改我们的打包命令
执行 npm run build会发现生成了以下目录(图片)
其中dist文件夹中的main.js就是我们需要在浏览器中实际运行的文件
当然实际运用中不会仅仅如此,下面让我们通过实际案例带你快速入手webpack
1.3 配置html模板js文件打包好了,但是我们不可能每次在html文件中手动引入打包好的js
可以这样配置打包名称
[JavaScript] 纯文本查看 复制代码 module.exports = {
// 省略其他配置
output: {
filename: '[name].[hash:8].js', // 打包后的文件名称
path: path.resolve(__dirname,'../dist') // 打包后的目录
}
}
这时候生成的dist目录文件如下
为了缓存,你会发现打包好的js文件的名称每次都不一样。webpack打包出来的js文件我们需要引入到html中,但是每次我们都手动修改js文件名显得很麻烦,因此我们需要一个插件来帮我们完成这件事情
npm i -D html-webpack-plugin
新建一个build同级的文件夹public,里面新建一个index.html
具体配置文件如下
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development', // 开发模式
entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
output: {
filename: '[name].[hash:8].js', // 打包后的文件名称
path: path.resolve(__dirname,'../dist') // 打包后的目录
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html')
})
]
}
生成目录如下(图片)
可以发现打包生成的js文件已经被自动引入html文件中
1.3.1 多入口文件如何开发
生成多个html-webpack-plugin实例来解决这个问题
[JavaScript] 纯文本查看 复制代码 const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development', // 开发模式
entry: {
main:path.resolve(__dirname,'../src/main.js'),
header:path.resolve(__dirname,'../src/header.js')
},
output: {
filename: '[name].[hash:8].js', // 打包后的文件名称
path: path.resolve(__dirname,'../dist') // 打包后的目录
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html'),
filename:'index.html',
chunks:['main'] // 与入口文件对应的模块名
}),
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/header.html'),
filename:'header.html',
chunks:['header'] // 与入口文件对应的模块名
}),
]
}
此时会发现生成以下目录
1.3.2 clean-webpack-plugin每次执行npm run build 会发现dist文件夹里会残留上次打包的文件,这里我们推荐一个plugin来帮我们在打包输出前清空文件夹clean-webpack-plugin
[JavaScript] 纯文本查看 复制代码 const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
// ...省略其他配置
plugins:[new CleanWebpackPlugin()]
}
1.4 引用CSS我们的入口文件是js,所以我们在入口js中引入我们的css文件
同时我们也需要一些loader来解析我们的css文件
npm i -D style-loader css-loader
如果我们使用less来构建样式,则需要多安装两个
npm i -D less less-loader
配置文件如下
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
module.exports = {
// ...省略其他配置
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader'] // 从右向左解析原则
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader'] // 从右向左解析原则
}
]
}
}
浏览器打开html如下
1.4.1 为css添加浏览器前缀
npm i -D postcss-loader autoprefixer
配置一下
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\.less$/,
use:['style-loader','css-loader','postcss-loader','less-loader'] // 从右向左解析原则
}
]
}
}
接下来,我们还需要引入autoprefixer使其生效,这里有两种方式 1,在项目根目录下创建一个postcss.config.js文件,配置如下: [JavaScript] 纯文本查看 复制代码 module.exports = {
plugins: [require('autoprefixer')] // 引用该插件即可了
}
2,直接在webpack.config.js里配置 [JavaScript] 纯文本查看 复制代码 // webpack.config.js
module.exports = {
//...省略其他配置
module:{
rules:[{
test:/\.less$/,
use:['style-loader','css-loader',{
loader:'postcss-loader',
options:{
plugins:[require('autoprefixer')]
}
},'less-loader'] // 从右向左解析原则
}]
}
}
这时候我们发现css通过style标签的方式添加到了html文件中,但是如果样式文件很多,全部添加到html中,难免显得混乱。这时候我们想用把css拆分出来用外链的形式引入css文件怎么做呢?这时候我们就需要借助插件来帮助我们 1.4.2 拆分css
npm i -D mini-css-extract-plugin
webpack 4.0以前,我们通过extract-text-webpack-plugin插件,把css样式从js文件中提取到单独的css文件中。webpack4.0以后,官方推荐使用mini-css-extract-plugin插件来打包css文件
配置文件如下
[JavaScript] 纯文本查看 复制代码 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
//...省略其他配置
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
],
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[id].css",
})
]
}
1.4.3 拆分多个css
这里需要说的细一点,上面我们所用到的mini-css-extract-plugin会将所有的css样式合并为一个css文件。如果你想拆分为一一对应的多个css文件,我们需要使用到extract-text-webpack-plugin,而目前mini-css-extract-plugin还不支持此功能。我们需要安装@next版本的extract-text-webpack-plugin
npm i -D extract-text-webpack-plugin@next
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
const path = require('path');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
let indexLess = new ExtractTextWebpackPlugin('index.less');
let indexCss = new ExtractTextWebpackPlugin('index.css');
module.exports = {
module:{
rules:[
{
test:/\.css$/,
use: indexCss.extract({
use: ['css-loader']
})
},
{
test:/\.less$/,
use: indexLess.extract({
use: ['css-loader','less-loader']
})
}
]
},
plugins:[
indexLess,
indexCss
]
}
1.5 打包 图片、字体、媒体、等文件
file-loader就是将文件在进行一些处理后(主要是处理文件名和路径、解析文件url),并将文件移动到输出的目录中
url-loader 一般与file-loader搭配使用,功能与 file-loader 类似,如果文件小于限制的大小。则会返回 base64 编码,否则使用 file-loader 将文件移动到输出的目录中
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
module.exports = {
// 省略其它配置 ...
module: {
rules: [
// ...
{
test: /\.(jpe?g|png|gif)$/i, //图片文件
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, //媒体文件
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, // 字体
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
}
]
},
]
}
}
1.6 用babel转义js文件为了使我们的js代码兼容更多的环境我们需要安装依赖 [JavaScript] 纯文本查看 复制代码 npm i -D babel-loader @babel/preset-env @babel/core
- 注意 babel-loader与babel-core的版本对应关系
- babel-loader 8.x 对应babel-core 7.x
- babel-loader 7.x 对应babel-core 6.x
配置如下
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
module.exports = {
// 省略其它配置 ...
module:{
rules:[
{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
},
exclude:/node_modules/
},
]
}
}
上面的babel-loader只会将 ES6/7/8语法转换为ES5语法,但是对新api并不会转换 例如(promise、Generator、Set、Maps、Proxy等)
此时我们需要借助babel-polyfill来帮助我们转换
[JavaScript] 纯文本查看 复制代码 npm i @babel/polyfill
[JavaScript] 纯文本查看 复制代码 // webpack.config.js
const path = require('path')
module.exports = {
entry: ["@babel/polyfill",path.resolve(__dirname,'../src/index.js')], // 入口文件
}
|