WebPack

这里有一个详细的说明,今后会跟下面的文档合并在一起。

1. 基础用法

相关源代码

这个例子本来是想用webpack来实现静态html的制作,如果是静态Html制作,要涉及到模板的应用,反复实验了几种情况后,发现都不满意。

  • 像react一样,将body中的内容注入到layout中,这种方法不能让程序自动刷新,所以失败了。
  • 与react的思路相反,正向引用,这种也失败了,因为不能向下面一级的嵌套内容传递参数。
  • 最后只能老老实实的写完整的html,放弃了使用模板技术。

1.1 功能分析

这是模拟的一个网站的数据结构

./src
├── components #演示了正向引用模板
│ ├── footer.html
│ └── header.html #这个模板中包含了参数,但是webpack不能将参数传入
├── css #演示了css的引用
│ ├── common
│ │ └── common.css
│ ├── global.css
│ └── page
│ └── login.css
├── imgs #演示了大图与小图的不同处理方法
│ ├── large.png
│ ├── logo.svg
│ └── small.png
├── js
│ ├── common
│ │ └── a-module.js #被引用的js文件
│ ├── global.js
│ └── page
│ └── login.js #这个文件中,调用了css内容,这样就可以打包到Html中了
├── layouts #模板文件,参考了react的思路,但是每次修改后,不能自动刷新
│ ├── blank
│ │ └── index.html
│ └── default
│ ├── footer.html
│ ├── header.html
│ └── index.html
└── pages
├── about.html #正向引用模板文件的效果,不能向第二级模板文件传递参数
├── index.html #layout效果,失败了,因为修改内容,不能刷新
├── login #layout效果,失败了,因为修改内容,不能刷新
│ └── login.html
└── success.html #推荐的的Html撰写效果
  • 处理html文件
    • 有一个index.html模板,可以根据这个模板生成html文件,并将打包的css,js,图片写入这个Html中。
    • 通过配置,可以生成多个Html文件。
    • 通过配置,将html与所需的资源文件关联在一起了。
  • 处理css文件
    • 有两种处理css的方式,一种是打包到js中,一种是单独生成css文件,然后在html中引用。
    • 这些项目是把css文件单独打包,这希望能获得更快的执行速度。
    • 可以给css添加后缀,这样不用使用ctrl+f5来清空css的缓存。
    • index.css引用了common.css,最终会打包成一个文件。
    • login.css会单独打包一个css文件。
    • 可以对css文件进行压缩,添加前缀去优化兼容性。
  • 处理图片
    • CSS文件中的背景图片,与html文件中的背景图片都需要处理
    • 大的图片生成到imgs目录中。
    • 小的图片做成base64编码,保存到css文件中,或者Html文件中。
    • 文件不添加后缀的随机编码,这样其他人可以引用这个图片文件。
  • 处理js文件
    • js文件可以打成不同的包
    • js文件之间可以相互引用
  • 要实现热更新,也就是修改任意一个文件,就可以在浏览中自动刷新,显示出修改后的效果。

1.2 安装组件

可以把下面的做成一个自动化脚本,下面的组件都会被安装到devDependencies

mkdir -p webpack-project/src/js
cd webpack-project
# code .
npm init -y
tyarn add webpack webpack-cli -D
# clean-webpack-plugin会在打包结束后帮我们清除/dist文件夹,每次打包时候先清空dist文件夹
tyarn add clean-webpack-plugin -D
# html-webpack-plugin:会在打包结束后,⾃动⽣成⼀个html⽂件,并把打包⽣成的js模块引⼊到该html中
tyarn add html-webpack-plugin -D
# css-loader: 分析css模块之间的关系,并合成⼀个css
# style-loader:把css-loader⽣成的内容,以style挂载到⻚⾯的heade部分 -d= --save-dev
tyarn add style-loader css-loader -D
# file-loader:原理是把打包⼊⼝中识别出的资源模块,移动到输出⽬录,并且返回⼀个地址名称
# webpack5 使用内置的asset,替换了这个loader
# tyarn add file-loader -D
# less-loader:把less语法转换成css
tyarn add less less-loader -D
# postcss-loader:兼容浏览器加兼容前缀
tyarn add postcss-loader autoprefixer -D
# webpack-dev-server:内置的web容器
tyarn add webpack-dev-server -D
# mini-css-extract-plugin:将css文件单独打包,按照这个做法,就不要在js中引用css了。
tyarn add mini-css-extract-plugin -D
# 可是尝试不安装
tyarn add ejs-loader -D
# 处理html中的图片,也可以压缩 HTML 字符串
tyarn add html-loader -D

1.3 源代码注意事项

  • 图片文件一定要使用:require
<img src="<%= require('@/imgs/logo.svg')%>"/>
  • 要引用模板文件时,需要添加
<%= require('html-loader!@/components/footer.html').default %>

1.4 配置package.json

  • 启动服务,有两种方法:start与start1

  • NODE_ENV=production 是将production传入到变量mode中,在这个webpack.config.js中使用

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "NODE_ENV=production webpack",
"build:pro": "NODE_ENV=production webpack",
"start": "NODE_ENV=production webpack-dev-server --open",
"start1": "NODE_ENV=production webpack serve --open"
},

1.5 配置webpack.config.js

这个是重点

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); //输出html文件的插件
const {CleanWebpackPlugin}=require("clean-webpack-plugin");//打包前清空disk的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //单独打包css
const webpack =require('webpack');
// 设置输出的变量 例如:"build": "NODE_ENV=production,可以根据不同的变量打包
const devMode = process.env.NODE_ENV !== "production";
// 读取某个片段文件的内容
var fs=require('fs');
const getFileContent=(fileName)=>{
var content = fs.readFileSync(fileName).toString();
return content;
};
/**
* 基本概念
* 入口(entry)
* 输出(output)
* 插件(plugin)
* 模式(mode)
* 环境(environment)
* devServer:模拟服务器
* module:loader:webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块
*/
module.exports = {
/**
* 配置别名,在程序中可以使用【import a from '@/a.js'】来找到地址
*/
resolve:{
alias:{
'@':path.join(__dirname,'src'),
}
},
/**
* 哪个文件为入口起点开始打包,也可以把Html当成入口
*/
entry:{
global:'./src/js/global.js',
login:'./src/js/page/login.js',
},
/**
* 输出的资源到哪里去,叫什么名字
* webpack默认是针对js进行输出的
*/
output:{
path:path.resolve(__dirname,'dist'),// 打包到dist目录下
filename:"js/[name]_[chunkhash:8].js", //多入口文件可以使用占位符打包
},
mode: "development", //设置开发环境,生产模式:production 开发模式:development
devtool:"inline-source-map", //源代码与打包后的代码的映射关系,可以了解一下sourceMap
/**
* 模拟服务器进行页面的预览
*/
"devServer": {
port: 3000,
hot:false, //官方网址说了:hot必须=false https://webpack.js.org/configuration/dev-server/#devserverlivereload
liveReload: true,
proxy:{ //如果了解antDesign,那么就理解这个了,静态页面,使用这个没有用
"/api":{
target:"http://localhost:9092"
}
},
},
/**
* 插件管理
*/
plugins:[
//失败的例子
new HtmlWebpackPlugin({
templateParameters: {
content: getFileContent('./src/pages/index.html'),
title:'首页'
},
template:"./src/layouts/blank/index.html",
inject:true,
cache:false,
chunks:['global'],
filename:'index.html'
// 控制压缩
/*
minify: {
collapseWhitespace: true, // 干掉空格
removeComments: true, // 干掉注释
removeAttributeQuotes: true, // 干掉双引号
removeEmptyAttributes: true // 干掉空属性
}
*/
}),
//失败的例子
new HtmlWebpackPlugin({
templateParameters: {
content: getFileContent('./src/pages/login/login.html'),
title:'登录'
},
template:"./src/layouts/default/index.html",
inject:true,
chunks:['login'],
filename:'login/login.html'
}),
//失败的例子
new HtmlWebpackPlugin({
title:'关于',
templateParameters: {
title:'关于'
},
template:"./src/pages/about.html",
inject:true,
chunks:['login'],
filename:'about.html'
}),
new HtmlWebpackPlugin({
title:'成功',
template:"./src/pages/success.html",
chunks:['login'],
filename:'success.html'
}),
// 打包前清除dist目录插件
new CleanWebpackPlugin(),
// 将css分离出来,单独打包
new MiniCssExtractPlugin({
filename:devMode ? "css/[name].css": "css/[name].[contenthash:8].css",
chunkFilename: devMode ? "[id].css" : "[id].[contenthash:8].css",
}),
],
/**
模式 loader是有顺序的,从右到左,从下到上,有些顺序不对会引发错误
loader是模块转换器,webpack默认只知道如何处理js与Json,那么其他格式的文件,例如css,图片,webpack就傻眼了。
那只能使用loader了,下面是几种常用的loader
*/
module:{
rules:[
/**
* 处理css
*/
{
test: /\.(less|css)$/, // 如果是css结尾的文件
use: [
MiniCssExtractPlugin.loader, // 如果其中这个,要把style-loader
//"style-loader", // 将css打入到js中
"css-loader",
"less-loader",
"postcss-loader", //兼容浏览器加兼容前缀
]
},
/**
* 处理资源文件
* webpack5之前我们处理静态资源比如。图片字体之类的资源的时候等,
* 需要用到url-loader,file-loader,raw-loader,webpack5则放弃了这三个loader,
* 这三个loader在github上也停止了更新。
* webpack5使用四种新增的资源模块(Asset Modules)替代了这些loader的功能。
asset/resource 将资源分割为单独的文件,并导出url,就是之前的 file-loader的功能.
asset/inline 将资源导出为dataURL(url(data:))的形式,之前的 url-loader的功能.
asset/source 将资源导出为源码(source code). 之前的 raw-loader 功能.
asset 自动选择导出为单独文件或者 dataURL形式(默认为8KB). 之前有url-loader设置asset size limit 限制实现。
*/
{
test: /\.(jpg|png|gif|jpeg|svg)$/,//处理图片资源
type: "asset",//使用webpack5内置的type
parser:{
dataUrlCondition:{
maxSize:8*1024 //data转成url的条件,也就是转成bas64的条件,maxSize相当于limit
}
},
generator:{//geneator中是个对象,配置下filename,和output中设置assetModuleFilename一样,将资源打包至imgs文件夹
filename:"imgs/[name][ext]" //[name]指原来的名字,[hash:6]取哈希的前六位,[ext]指原来的扩展名
}
},
/**
* 处理html中的图片 这个不能添加,添加了原有的就没有效果了
*/
// {
// test: /\.html$/i,
// loader: "html-loader",
// },
// {
// // 对模版文件使用loader 这个不能添加,添加了原先的就没有效果了。
// test: /\.ejs$/,
// use: 'ejs-loader'
// },
/**
* 处理字体文件
*/
{
test: /\.(woff2|woff)$/, //匹配字体规则
type: "asset/resource",
}
]
},
}

1.6 打包调试

yarn build

tailwind css intellisense

tailwind css explorer