node: v14.16.0
webpack: 5.55.1
webpack-cli: 4.8.0
node 环境下
npm init
//会生成 package.json文件
npm i -D webpack webpack-cli
- npm i -D 为 npm install --save-dev 的缩写
- npm i -S 为 npm install --save 的缩写
main.js:
console.log('输出点文字')
"scripts": {
"build": "webpack src/main.js" //我用了 ./src/main.js 才成功,前面那样 url,报错
}
npm run build
此时如果生成了一个 dist 文件夹,并且内部含有 main.js 说明打包成功!
- dist
- main.js (webpack 打包生成)
- src
- main.js
- package.json
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') // 打包后的目录
}
}
"scripts": {
"build": "webpack --config build/webpack.config.js"
}
- dist
- output.js
js 文件打包好了,但是我们不可能每次在 html 文件中手动引入打包好的 js,为了清除 js 缓存,我们一般做如下配置:
webpack.config.js 片段
module.exports = {
// 省略其他配置
output: {
filename: '[name].[hash:8].js', // 打包后的文件名
path: path.resolve(__dirname,'../dist') // 打包后文件保存的目录
}
}
这时候生成的 dist 目录文件如下:
- dist
- main.cac25ec2.js 如何引入每次打包文件名都不同的 js 文件?我们需要一个插件:
npm i -D html-webpack-plugin
- build
- public
- index.html
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')
})
]
}
index.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>Document</title>
</head>
<body>
<p>使用 html-webpack-plugin 自动引入 js 文件(随机js文件名)</p>
</body>
</html>
ok,执行以下:
npm run build
dist 目录下生成了新的 main.随即符.js 和 index.html
- dist
- index.html
- main.819ddf57.js
index.html 自动插入了打包的 js 文件
<script defer src="main.819ddf57.js"></script>
<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>Document</title>
<script defer src="main.819ddf57.js"></script></head>
<body>
<p>使用 html-webpack-plugin 自动引入 js 文件(随机js文件名)</p>
</body>
</html>
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode:'development',
//单入口写法 entry: path.resolve(__dirname,'../src/main.js'),
entry: {
main: path.resolve(__dirname,'../src/main.js'), //入口文件 1 模块
header:path.resolve(__dirname,'../src/header.js') //入口文件 2 模块
},
output:{
filename: '[name].[hash:3].js', //打包后的文件名称
path: path.resolve(__dirname,'../dist') //打包后的存储目录
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html'),
filename:'index.html', //必须写,不写会出现文档链接错误(index.html 链接了 header.a0f.js)
chunks:['main'] //与入口文件对应的模块名
}),
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/header.html'),
filename:'header.html', //必须写,不写会出现文档链接错误(index.html 链接了 header.a0f.js)
chunks:['header'] //与入口文件对应的模块名
})
]
}
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
// ...省略其他配置
plugins:[new CleanWebpackPlugin()]
}
要安装一下啊
npm i -D clean-webpack-plugin
(教程未提示安装,当然,我是新手)
我们的入口文件是 main.js,所以我们在入口 js 中引入我们的 css 文件
main.js 片段
import './assets/index.css' // hN 正确路径:'../assets/index.css'
import './assets/index.less'
//。。。
同时,我们也需要使用一些 loader 来解析我们的 css 文件
npm i -D style-loader css-loader
如果我们使用 less 来构建样式,则需要多安装两个
npm i -D less less-loader
配置文件如下:
webpack.config.js
module.exports = {
//。。。省略其他配置
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader'] // 从右向左 ← 解析原则
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader'] // 从右向左 ← 解析原则
}
]
}
}
说明:此处的 css 代码并不直接生成在 dist/index.html 中,仍是通过打包的 main.[hash].js 动态插入到 index.html 中<style>/插入的css/</style> 标签的
webpack.config.js 片段
module.exports = {
module:{
rules:[
{
test: /\.less$/,
use:['style-loader','css-loader','postcss-loader','less-loader']
}
]
}
}
postcss.config.js
module.exports = {
plugins: [require('autoprefixer')] // 引用该插件即可了
}
webpack.config.js 片段
//...省略其他配置
module:[
rules:[
{
test:/\.less$/,
use:['style-loader',
'css-loader',
{
loader:'postcss-loader',
options:{ // hN 经测试,添加此属性会报错,去掉 options 属性,直接调用 postcss-loader 即可
plugins:[require('autoprefixer')]
}
},
'less-loader'] //从右向左解析原则
}
]
]
这时候我们发现css通过style标签的方式添加到了html文件中,但是如果样式文件很多,全部添加到html 中,难免显得混乱。这时候我们想要把 css 拆分出来用外链的形式引入 css 文件。现在需要一个插件 mini-css-extract-plugin
webpack 4.0以前,我们通过 extract-text-webpack-plugin 插件,把css 样式从js文件中提取到单独的css文件中。webpack 4.0 以后,官方推荐使用 mini-css-extract-plugin 插件来打包 css 文件。
配置文件 webpack.config.js 如下
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
//...省略其他配置
module: {
rules: [
{
test: /\.less$|.css$/,
user: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[id].css"
})
]
}
npm run build
之前引入到 main.js 中的css文件会合并+抽出(多个css会依次合并)为 /dist/main.[hash].css,并使用 <style> 标签插入到 index.html 中
上面我们用到的 mini-css-extract-plugin 会将所有的css样式合并为一个css文件,如果想拆分为一一对应的多个css文件,我们需要使用到 extract-text-webpack-plugin,我们需要安装 @next 版本的 extract-text-webpack-plugin。( mini-css-extract-plugin 还不支持此功能)
npm i -D extract-text-webpack-plugin@next
webpack.config.js 片段
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:/\.css$/,
use: ['css-loader','less-loader']
}
]
},
plugins:[
indexLess,
indexCssS
]
}
安装 file-loader 和 url-loader
cnpm i -D file-loader
cnpm i -D url-loader
file-loader 就是将文件进行一些处理后(主要处理文件名、路径、解析文件url),并将文件移到纯输出目录。 url-loader 一般与 file-loader 配合使用,功能与 file-loader 类似,如果文件 <= limit 大小,则返回 base64 编码,否则使用 file-loader 将文件输出到配置目录。
webpack.config.js 片段
module.exports = {
// 省略其他配置。。
mudule: {
rules: [
//...
{
test: /\.(jpe?g|png|gif)$/i, // i = ignore (正则默认区分大小写,加 i 不区分大小写)
use: [
{
loader: 'url-loader',
options: {
limit: 10240, // 小于等于此值,转 base64
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
}
]
}
}
为了使我们的 js 代码兼容更多的环境我们需要安装依赖
npm i -D babel-loader @babel/preset-env @babel/core
@babel/core 模块是 babel 的核心库
配置一下: webpack.config.js 片段
module.exports = {
// 其他配置...
module: {
rules:[
{
test:/\.js$/,
use:{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
},
exclude: /node_modules/
}
]
}
}
★ js 文件中声明的 function 方法为何是 xx is not defined ?
因为 webpack 的打包是基于模块来打包的,也就是说经过打包的文件代码是被打包到一个函数里,此时所有定义的变量或者方法已变成局部的。有了独立的作用域,定义变量,声明函数都不会污染全局作用域 直接使用 function 的方法:提升作用域window.方法名 = function (){ }
安装
npm i -D webpack-dev-server
webpack.config.js 片段
const Webpack = require('webpack');
module.exports = {
//...
devServer:{
port:3000,
hot:true,
contentBase: '../dist' // webpack5 实测,contentBase 已废弃,改用 static 属性
},
plugins:[
new Webpack.HotModuleReplacementPlugin()
]
}
<style> .red,red{color:red;} </style>package.json 配置启动服务命令
js "scripts": { "dev": "webpack-dev-server --config build/webpack.config.js --open" }
命令行npm run dev
来启动服务。一点发现:启动服务后,dist 目录原有经 build 打包的文件会被清理掉。localhost运行的文件并不是在 dist 目录。baidu 解释:webpack 服务运行的文件是在内存中