实现步骤
- 实现能打包js的项目;
- 处理HTML文件并引用js的功能
- 处理css
- 处理vue文件
- 处理ts
- 完整实例
- 优化和兼容(后续在其它笔记)
环境说明
- 编辑器:
vscode; node版本:v22.11.0- 安装包工具: npm
实现能打包js的项目
-
初始化项目:新建一个文件夹在终端中运行
npm init -y,会生成一个package.json文件; -
下载
webpack相关插件:npm i webpack webpack-cli webpack-dev-server -D; -
创建
webpack配置文件: 在根目录创建webpack.config.js,webpack的相关配置都会在这里; -
新建打包的入口文件: 在新建
src文件夹,以及在src文件夹内新建main.js文件(作为入口文件),新增index.html(用来调用main.js),文件结构如下: -
配置
webpack的入口、出口以及开发环境信息: 在webpack.config.js中配置如下const path = require("path"); module.exports = { entry: { // webpack的入口 main: { import: path.resolve(__dirname, 'src/main.js'), } }, output: { path: path.resolve(__dirname, 'dist'), // 打包在那个文件夹 filename: '[name].js', // 打包生成的文件名,name会转化为入口entry的key值 }, devServer: { static: { // 静态文件在那个文件夹,一般在根目录的public directory: path.resolve(__dirname, 'public'), }, port: 9001, // 使用的端口 hot: true, // 是否热更新 open: true, // 启动后自动打开浏览器,支持指定浏览器 compress: true, // 启用GZIP压缩 }, } -
创建webpack命令; 在
package.json设置script的dev为和build属性"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack server --mode development", "build": "webpack --mode production" }, -
打包生成文件:执行
npm run build,会在根目录生成dist文件,并在dist文件夹中生成main.js -
每次打包前都清除dist文件夹的文件
-
安装: npm install --save-dev clean-webpack-plugin
-
引入:在webpack.config.js引入
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); -
在插件处配置:
```js plugins: [ new CleanWebpackPlugin(), // 清除dist文件夹下的文件 ] ```
-
-
为了方便查看打包后的代码,我们不将js压缩
module.exports = {
optimization: {
minimize: false
},
}
处理HTML并自动引入js
- 让HTML调用
main.js并且打包到dist文件中-
下载生成HTML文件的插件
npm i html-webpack-plugin --save-dev -
在
webpack.config.js引入插件const HtmlWebpackPlugin = require("html-webpack-plugin"); -
在
webpack.config.js使用该插件const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { plugins: [ new CleanWebpackPlugin(), // 清除dist文件夹下的文件 new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src/index.html'), // 入口文件 filename: 'index.html', chunks: ['main'] // 引用对应的js }), ] } -
执行npm run build会在dist文件夹下多一个index.html,执行npm run dev会打开一个浏览器页签
-
处理css
- 安装
loader:npm i style-loader css-loader -D,其中style-loader是将css代码注入到DOM中,css是将css代码处理成js的格式; - 配置
webpack.config.js:module.exports = { module: { rules: [ { test: /\.css$/, // 匹配 CSS 文件 use: ['style-loader', 'css-loader'], // 使用 style-loader 和 css-loader }, ], }, - 新建css文件:在src文件夹下创建
assets/css/style.css文件; - 引用css文件: 在main.js中引用css,
import "./assets/css/main.css"; - 执行
webpack:npm run build或者npm run dev看一下css有没有加载成功;
处理图片等文件
- 安装插件:安装
file-loader或url-loader都行,建议使用url-loader,可以将小图片转化为DATA URL,可以减少http请求,并且url-loader包含file-loadernpm install url-loader -D - 配置
webpack.config.js:
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于 8KB 的文件将被转换为 Data URL
name: '[path][name].[ext]',
},
},
],
},
],
},
处理vue文件
- 安装插件:
vue要打包到项目里的npm i vue, 两个打包用的vue-loader和vue-template-compiler(处理模板语法),npm i vue-loader vue-template-compiler -D - 配置文件:
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
}
],
},
plugins: [
new VueLoaderPlugin()
]
}
- 在
src目录下创建App.vue - 在
main.js引用,并把App挂载到body上
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App); // 生成一个app组件
app.mount('#app'); // 用这个组件替换id为app的标签
处理ts(组合API)
- 安装:
npm i typescript ts-loader -D; - 新增
tyconfig.json文件:
{
"compilerOptions": {
"target": "ES5", // 可以兼容巨大部分的浏览器了
"module": "ESNext", // 用来支持较新的模板语法
"sourceMap": true, // 方便调试
"strict": true,
"jsx": "preserve", // 处理JSX语法,没有的话可以移除
"importHelpers": true, //
"moduleResolution": "node",
"esModuleInterop": true, // experimentalDecorators和esModuleInterop用于支持装饰器和更好的模块互操作性
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [ // 编译那些文件的ts
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"exclude": [
"node_modules"
]
}
- 配置
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/], // 允许在 .vue 文件中使用 TypeScript
},
exclude: /node_modules/
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.vue', '.js'],
alias: { // 给固定路径起别名
'@': path.resolve(__dirname, 'src')
}
},
}
- 使用ts:在vue中设置
<script lang="ts">,里面就可以写ts语法了 - 注意:如果项目中只有vue使用了ts,
tsconfig.json会报错,找不到include下的ts文件
完整实例
- 目录结构
package.json文件
{
"name": "webpack1",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack server --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"css-loader": "^7.1.2",
"html-webpack-plugin": "^5.6.3",
"style-loader": "^4.0.0",
"ts-loader": "^9.5.1",
"typescript": "^5.6.3",
"vue-loader": "^17.4.2",
"vue-template-compiler": "^2.7.16",
"webpack": "^5.96.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.1.0"
},
"dependencies": {
"vue": "^3.5.13"
}
}
webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
entry: { // webpack的入口
main: {
import: path.resolve(__dirname, 'src/main.js'),
}
},
output: {
path: path.resolve(__dirname, 'dist'), // 打包在那个文件夹
filename: '[name].js', // 打包生成的文件名,name会转化为入口entry的key值
},
devServer: {
static: { // 静态文件在那个文件夹,一般在根目录的public
directory: path.resolve(__dirname, 'public'),
},
port: 9002, // 使用的端口
hot: true, // 是否热更新
open: true, // 启动后自动打开浏览器,支持指定浏览器
compress: true, // 启用GZIP压缩
},
optimization: {
minimize: false
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于 8KB 的文件将被转换为 Data URL
name: '[path][name].[ext]',
},
},
],
},
{
test: /\.css$/, // 匹配 CSS 文件
use: ['style-loader', 'css-loader'], // 使用 style-loader 和 css-loader
},
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/], // 允许在 .vue 文件中使用 TypeScript
},
exclude: /node_modules/
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.vue', '.js'],
alias: { // 给固定路径起别名
'@': path.resolve(__dirname, 'src')
}
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src/index.html'), // 入口文件
filename: 'index.html',
chunks: ['main'] // 引用对应的js
}),
]
}
tsconfig.json
{
"compilerOptions": {
"target": "ES5", // 可以兼容巨大部分的浏览器了
"module": "ESNext", // 用来支持较新的模板语法
"sourceMap": true, // 方便调试
"strict": true,
"jsx": "preserve", // 处理JSX语法,没有的话可以移除
"importHelpers": true, //
"moduleResolution": "node",
"esModuleInterop": true, // experimentalDecorators和esModuleInterop用于支持装饰器和更好的模块互操作性
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [ // 编译那些文件的ts
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"exclude": [
"node_modules"
]
}
App.vue
<template>
<!-- 在这里编写模板内容,比如可以添加一些按钮、文本等元素来与方法进行交互 -->
<div>
<button @click="handleClick">点击我</button>
<p>{{ message }}</p>
</div>
</template>
<script setup lang="ts">
import { Ref, ref } from 'vue';
// 定义响应式数据
const message: Ref<string> = ref('初始消息');
// 定义方法
const handleClick = (): void => {
message.value = '按钮被点击后更新的消息';
};
</script>
<style scoped>
button {
color: skyblue;
border: 1px solid gray;
border-radius: 4px;
&:hover {
color: blue;
}
}
</style>
main.js
<template>
<!-- 在这里编写模板内容,比如可以添加一些按钮、文本等元素来与方法进行交互 -->
<div>
<button @click="handleClick">点击我</button>
<p>{{ message }}</p>
</div>
</template>
<script setup lang="ts">
import { Ref, ref } from 'vue';
// 定义响应式数据
const message: Ref<string> = ref('初始消息');
// 定义方法
const handleClick = (): void => {
message.value = '按钮被点击后更新的消息';
};
</script>
<style scoped>
button {
color: skyblue;
border: 1px solid gray;
border-radius: 4px;
&:hover {
color: blue;
}
}
</style>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
浏览器兼容与优化(后续其它笔记)
- 兼容
- js:需要通过
babel兼容 - css:需要
postcss和autoprefixer
- js:需要通过
- 性能优化
- 压缩,包拆分,将静态代码抽到一个包,删除无用代码等
- 打包优化
- 多线程打包,不同环境配置不同的配置文件,开发环境css不需要到css文件和不需要压缩,而生产环境要