Webpack知识点
Webpack
webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具,将各种类型资源打包编译为最基础的html、js、css、img等
安装
创建npm项目
npm init -y
安装webpack以及脚手架
npm install webpack webpack-cli --save-dev
webpack文件夹目录
src/index.js
console.log("项目入口");
import { createButton } from "./utils/createbutton";
createButton("首页按钮", () => {
console.log("点击了首页按钮");
})
引入外部模块 utils/createButton.js
export function createButton(text, clickCallBack) {
let button = document.createElement("button");
button.innerText = text;
button.onclick = clickCallBack;
document.body.appendChild(button);
}
dist/index.html
<script src="./main.js"></script>
webpack操作
npx webpack
npx可以用于本地项目安装的指令工具
会在package.json同级目录编译生成dist文件夹 存放编译好的main.js
配置文件
package.json同级目录新建webpack.config.js
入口 entry
出口output
var path = require("path")
module.exports = {
// // 入口
// entry: "./src/index.js",//指明打包开始文件
// // 出口
// output: {
// filename: "main.js",//指明打包成果文件名
// path: path.resolve(__dirname, 'dist'),//指明打包成果目录
// clean: true,//清理dist下无用的文件夹
// },
resolve: {
// resolve 解析方式 alias别名 @==src目录
alias: {
"@": path.resolve(__dirname, "src")
}
},
module: {
// 不同的文件 需要不同的加载规则
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
}
配置项目的npm运行命令,修改package.json文件
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
运行npm命令执行打包
npm run build
加载资源
src目录下新建静态资源文件
加载 CSS
需要安装 style-loader 和 css-loader,并在 module 配置 中添加这些 loader:
npm install --save-dev style-loader css-loader
webpack.config.js
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
‘style-loader’ 在前,而 ‘css-loader’ 在后。如果不遵守此约定,webpack 可能会抛出错误。
加载 images 图像
在 webpack 5 中,可以使用内置的 Asset Modules
webpack.config.js
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
加载 fonts 字体
webpack.config.js
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
加载数据
要导入 CSV、TSV 和 XML,你可以使用 csv-loader 和 xml-loader
npm install --save-dev csv-loader xml-loader
webpack.config.js
{
test: /\.(csv|tsv)$/i,
use: ['csv-loader'],
},
{
test: /\.xml$/i,
use: ['xml-loader'],
},
自定义 JSON 模块 parser
通过使用 自定义 parser 替代特定的 webpack loader,可以将任何 toml、yaml 或 json5 文件作为 JSON 模块导入
安装 toml,yamljs 和 json5 的 packages
npm install toml yamljs json5 --save-dev
webpack.config.js
const path = require('path');
const toml = require('toml');
const yaml = require('yamljs');
const json5 = require('json5');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
{
test: /\.(csv|tsv)$/i,
use: ['csv-loader'],
},
{
test: /\.xml$/i,
use: ['xml-loader'],
},
{
test: /\.toml$/i,
type: 'json',
parser: {
parse: toml.parse,
},
},
{
test: /\.yaml$/i,
type: 'json',
parser: {
parse: yaml.parse,
},
},
{
test: /\.json5$/i,
type: 'json',
parser: {
parse: json5.parse,
},
},
],
},
};
src/index.js
import _ from 'lodash';
import './style.css';
import Icon from './icon.png';
import Data from './data.xml';
import Notes from './data.csv';
import toml from './data.toml';
import yaml from './data.yaml';
import json from './data.json5';
console.log(toml.title); // output `TOML Example`
console.log(toml.owner.name); // output `Tom Preston-Werner`
console.log(yaml.title); // output `YAML Example`
console.log(yaml.owner.name); // output `Tom Preston-Werner`
console.log(json.title); // output `JSON5 Example`
console.log(json.owner.name); // output `Tom Preston-Werner`
function component() {
const element = document.createElement('div');
// Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
element.classList.add('hello');
// Add the image to our existing div.
const myIcon = new Image();
myIcon.src = Icon;
element.appendChild(myIcon);
console.log(Data);
console.log(Notes);
return element;
}
document.body.appendChild(component());
代码分割
将js文件拆分为多个,以便按需加载
新建/src/components/header.js
console.log("header入口");
index.js引入
import "@/components/header.js"
多入口与多出口
配置多个入口文件
entry:{
index:"@/index.js",
header:"@/components/header.js"
},
每个入口文件都会被自动引入index.html
在index.js中不需要在引入header.js
配置多个出口文件
output:{
filename:"[name].bundle.js",
path:path.resolve(__dirname, 'dist'),
clean:true
},
重复导入
修改header.js
console.log("header入口");
import { createButton } from "@/utils/createbutton";
createButton("header按钮",()=>{
console.log("点击了header按钮");
})
此时工具模块createButton被同时打包到了index.bundle.js和header.bundle.js
解决方案:
将createButton作为一个单独模块,
header.js与index.js依赖createButton,
重新配置入口文件
entry:{
index:{
import:"@/index.js",
dependOn:["createbutton"]
},
header:{
import:"@/components/header.js",
dependOn:["createbutton"]
},
createbutton:{
import:"@/utils/createbutton.js"
}
},
动态导入
去除header.js的入口配置
entry:{
index:{
import:"@/index.js",
dependOn:["createbutton"]
},
// header:{
// import:"@/components/header.js",
// dependOn:["createbutton"]
// },
createbutton:{
import:"@/utils/createbutton.js"
}
},
点击首页按钮时创建header
import(/* webpackChunkName:"header" */"@/components/header.js").then(()=>{
console.log("header导入完毕");
})
插件
HtmlWebpackPlugin
html5自动生成并引入bundle包
安装
npm install --save-dev html-webpack-plugin
配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [new HtmlWebpackPlugin()],
MiniCssExtractPlugin
将css从js中剥离,减少js文件大小
安装
npm install --save-dev mini-css-extract-plugin
配置
plugins: [new MiniCssExtractPlugin()],
use: [MiniCssExtractPlugin.loader, "css-loader"],
CssMinimizerWebpackPlugin
将css压缩
安装
npm install css-minimizer-webpack-plugin --save-dev
配置
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
},
TerserWebpackPlugin
将html压缩
webpack5 自带不需要安装
配置
const TerserPlugin = require("terser-webpack-plugin");
优化器配置
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
开发环境
mode:"development"
一般都是在npm指令中写
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production",
"serve": "webpack serve --mode development"
},
开发工具
webpack-dev-server
npm install --save-dev webpack-dev-server
devServer
// 安装了webpack-dev-serve以后会启用配置
devServer: {
host: "172.20.10.12",
port: 9999,
open: true,
proxy: {
},
},
使用webpack搭建vue脚手架
- 新建文件夹 webpack-vue
- 初始化npm项目
npm init -y
- 安装webpack工具
npm install webpack webpack-cli --save-dev
- 安装devServer
npm install --save-dev webpack-dev-server
- 添加运行指令
"build": "webpack --mode production",
"serve": "webpack serve --mode development"
- 根目录新建入口文件
src/main.js
console.log("项目入口");
- wepack配置文件
webpack.config.js
const path = require("path")
module.exports={
entry:"./src/main.js",
output:{
filename:"[name].bundle.js",
path:path.resolve(__dirname, "dist")
}
}
- 新建html页面加载bundle
dist/index.html
<!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>Document</title>
</head>
<body>
<script src="./main.bundle.js"></script>
</body>
</html>
- 安装vue
npm install vue
- 加载vue文件
main.js
console.log("项目入口");
import { createApp } from "vue"
import App from "./App.vue"
createApp(App).mount("#app")
App.vue
<template>
<div id="app">
<h1>我是App</h1>
<button @click="count++">点击{{ count }}</button>
<div class="nav">
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</div>
<router-view></router-view>
</div>
</template>
<script setup>
import { ref } from "vue"
const count = ref(10)
</script>
<style lang="less">
#app {
button {
color: red;
}
}
</style>
安装npm install -D vue-loader
修改配置
const {VueLoaderPlugin} = require("vue-loader")
{ test: /\.vue$/i, use: 'vue-loader' }
new VueLoaderPlugin()
加载less与css
- vue-router使用
安装npm install vue-router
新建文件
/src/views/HomeView.vue
<template>
<div class="home">
<h1>首页</h1>
</div>
</template>
/src/views/AboutView.vue
<template>
<div class="about">
<h1>关于</h1>
</div>
</template>
新建/src/router/index.js
import { createRouter, createWebHashHistory } from "vue-router"
import HomeVue from "@/views/HomeView.vue"
const routes = [
{ path: '/', component: HomeVue },
{ path: '/about', component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue') },
]
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
export default router
main.js引入
console.log("项目入口");
import { createApp } from "vue"
import App from "@/App.vue"
import router from "./router"
const app = createApp(App)
app.use(router)
app.mount("#app")
- 在根目录新建public/index.html
<!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>手撸VUE脚手架</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
安装
npm install --save-dev html-webpack-plugin
配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template:"./public/index.html"
})
]