前端工程化的核心就是webpack
了,而光看官方不行,不能闭门造车啊,所以必须游离于各大社区,学习各位大佬的技术与见解,亲自动手配置项目
才行。之前有提到一个前端工程化的学习之路,那包含了模块化、包管理器、构建工具、脚手架
,这次的项目配置
练习就多多少少涉及到其中的知识点了。
开搞,练习配置一个ts + vue
的工程。
一、 构建项目初始目录
1. 生成ts
的配置文件
命令:tsc --init
(tips:如果电脑是mac,且提示zsh: command not found: tsc
,那就先安装ts
,命令:sudo npm install typescript -g //全局安装typesrcpt
)
现在这个文件报错哈,先配一下,让它去找src
目录下的文件。
ts
{
...
"include": [
"src/**/*"
]
}
2.生成package.json
文件
命令:npm init -y
3.新增其他文件
webpack.config.js
、index.html
。
4.新建src
文件夹
新增文件,main.js
、App.vue
和shim.d.ts
二、安装webpack依赖
这里就是涉及包管理
和构建工具
的基础知识了。
1. 安装 webpack
相关
依赖:webpack
,webpack5
以上需要一起安装webpack-cli
。
命令:npm i webpack webpack-cli -D
现在安装完这两个依赖就可以打包了,但开发的时候需要看效果哈,所以还得再本地开个服务,就是开发服务器
哈。
依赖:webpack-dev-server
命令:npm i webpack-dev-server -D
现在和webpack
相关的是安装完了。
还有配置一下打包和启动命令。
3.基本配置webpack.config.js
1. 基本打包配置
webpack
是基于node.js
环境的,所以按照CommonJs
标准进行模块导出。 使用webpack
提供的声明文件,则相关属性有智能提示。
js
const { Configuration } = require("webpack"); //声明文件
const path = require("node:path");
/**
* @type{Configuration}
*/
const config = {
mode: "development",
entry: "./src/main.ts", //入口文件
output: path.resolve(__dirname, "dist"), //生成目录
filename: "bundle.js", //打包后的文件
};
module.exports = config;
到这里已经是可以进行打包了,可以实验一下。
这样就是基本的打包功能已经实现了哈😉!!
2. 解析js
语法配置
解析文件配的是loader
,比如要支持scss
预编译,配的就是loader
。
依赖:ts-loader
和typescript
命令:npm i ts-loader typescript -D
js
const config = {
...
module: {
rules: [
{ test: /\.ts$/, //正则,以ts结尾
use: "ts-loader", //使用 loader
exclude: /node_modules/ //除了这个模块
}
],
},
}
三、支持vue
语法
1. 安装依赖
依赖:vue
命令:npm i vue
2.vue
语法配置
js
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.mount("#app");
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>
现在是已经配置好了vue
,但现在html
和webpack
还没有联系,那就需要让他们产生关联了。安装一个插件即可。 依赖:html-webpack-plugin
命令:npm i html-webpack-plugin -D
js
//webpack.config.js
...
const HtmlWebpackPlugin = require("html-webpack-plugin");
const config = {
...
plugins: [new HtmlWebpackPlugin({ template: "index.html" })], //webpack 的插件集合,都是对象,需要 new
...
};
这下打包的时候,就会以index.html
为模板。
嘿嘿,是不是就可以npm run dev
跑起来了? nonono😴,vue
使用的是.vue
结尾的文件,webpack
不能编译啊,所以还得像之前一样,使用loader
来处理。
依赖:vue-loader
命令:npm i vue-loader -D
js
//webpack.config.js
const config = {
...
module: {
rules: [
{
test: /\.ts$/, //正则,以ts结尾
use: "ts-loader", //使用 loader
},
{
test: /\.vue$/,
use: "vue-loader",
},
],
},
};
这下wepack
就能识别了,npm run dev
来试试。。。。。 啊哦,报错了
啥意思,用过ts
都多多少少会碰到,就是缺少对应的类型声明
。
.js
//shim.d.ts
declare module "*.vue" {
import { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}
这下就好了。唉,还有报错:
说我们缺少了一个pugin
,好,引入它。
js
//webpack.config.js
...
const { VueLoaderPlugin } = require("vue-loader");
const config = {
...
plugins: [
new HtmlWebpackPlugin({ template: "index.html" }),
new VueLoaderPlugin(),
],
...
};
这下就没报错了,成功启动😎😎! vue
的基本功能都能使用了。
3. vue
文件里的ts
配置
经过上面的配置,已经是可以使用vue
的语法了,但是vue
是使用ts
还是不行,所以还得来配置。对之前的 ts
配置进行加工。
js
//webpack.config.js
const config = {
...
module: {
rules: [
{
test: /\.ts$/, //正则,以ts结尾
use: {
loader: "ts-loader",
options: {
appendTsSuffixTo: [/\.vue$/],
},
},
},
...
],
},
html
<template>
<div>{{ num }}</div>
<button @click="onCount">++</button>
</template>
<script setup lang="ts">
import { ref } from "vue";
const num = ref<number>(222);
const onCount = () => {
num.value++;
};
</script>
这下就OK了,哈哈哈😌。
对了,加点东西,
js
//webpack.config.js
const config = {
...
stats:'errors-only',//控制台只输出错误相关的
...
四、支持样式、图片等
1.css
配置
依赖:css-loader
、style-loader
命令:npm i css-loader style-loader -D
所有的样式都是由css-loader
统一解析,解析完之后,再交给style-loader
。css-loader
解析之后,会通过js
向html
里动态地插入style
标签,这就是style-loader
的作用。
js
//webpack.config.js
const config = {
...
module: {
rules: [
{
...
test: /\.css$/,
use: ["style-loader", "css-loader"], //从右往左解析
},
...
],
},
2. scss
配置
依赖:sass sass-lader
命令:npm i sass sass-loader -D
有点地方有出入了,在style
里我们是会这样写scss
,那在webpack
里的test
怎么写呢?
写成scss
或sass
都会报错!!看一下官网 sass-loader
js
//webpack.config.js
const config = {
...
module: {
rules: [
{
...
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"]
},
...
],
},
同理,less
也是这么配的。
3. postCSS
配置
使用postCSS
,使样式在各个浏览器兼容性问题自动配置。
依赖:postcss-loader
、autoprefixer
命令:npm i postcss-loader autoprefixer -D
在项目根目录创建postcss.config.js
文件。
js
//postcss.config.js
const Autoprefixer = require("autoprefixer");
module.exports = {
plugins: [Autoprefixer],
};
在webpack.config.js
里对css
进行处理。
js
//webpack.config.js
...
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"]
},
...
4.图片、字体配置
依赖:url-loader
、file-loader
命令:npm i url-loader file-loader -D
其中file-loader
是不需要配置的。
注:对于资源模块,其实在w5已经不需要这些loader了,有更方便的配法 资源模块
js
//webpack.config.js
...
{
test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
use: [
{
loader: "url-loader",
options: {
limit: 100 * 1024,//文件小于时,会转为base64
},
},
],
},
...
正常情况下,到这里就没问题了。但是但是报错,就是文件类型的问题。这时我们需要创一个声明文件image.d.ts
js
/* images.d.ts文件 */
declare module "*.svg";
declare module "*.png";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.gif";
declare module "*.bmp";
declare module "*.tiff";
完善一下tsconfig.json
,
js
...
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
]
!!!😫😫😫。这时候头疼的东西来了,使用img
标签就能让图片展示,使用添加背景的方式就是不能,原因就是路径错误。啊这个路径错误找了好久,个把小时都搞不定,后面才是阴差阳错的搞定了。 !! 得在option
对象里添加一个属性esModule:false
,真的是头都麻了。
5.语法兼容配置
webpack
只能兼容普通语法,高级的语法不行,所以还得配。
五、处理第三方包
1. js
这时候,项目已经是比较全了,这时候我们可以安装一些第三方库,比如moment
、elementUI
和echars
等等,这时打包的话会将所有的东西都放在boundle.js
里。
如果以后第三方工具越来越多,那这个bundle.js
的文件就会越来越大,那就会阻塞浏览器的渲染,导致加载时间越来越长。这时我们就可以进行分包
,把一些公共依赖或者第三方模块拆出来。
js
//webpack.config.js
const config = {
...
output: {
path: path.resolve(__dirname, "dist"), //生成目录
filename: "[name].[contenthash:8].bundle.js", //打包生成的文件名
clean: true, //清空打包结果
},
...
// 优化拆分
optimization: {
splitChunks: {
cacheGroups: {
moment: {
name: "moment", //文件名
chunks: "all", // 不分异步同步
test: /[\\/]node_modules[\\/]moment[\\/]/,
},
commons: {
name: "commons",
chunks: "all",
minChunks: 2, //同个依赖被引用超过2个,就会被拆分
},
},
},
},
}
2.css
现在已经可以正常将第三方包拆分出来了,但是,我们写了css
样式,这个并没有把css
分出来。这时候是会通过js
去动态地插入style
标签,这样性能其实不是很好啊,我们是希望通过link
的方式去引入,把css
文件单独抽离出来。
依赖:mini-css-exract-plugin
命令:npm i mini-css-extract-plugin -D
js
//webpack.config.js
const config = {
...
plugins: [
...
new MiniCssExtractPlugin(),
],
...
module: {
rules: [
...
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"], //从右往左解析
},
...
],
},
}
六、打包目录
现在打包时,可以打js
、css
和图片
了,不过他们都挤在dist
文件夹里,现在优化一下,让它们有自己的文件夹。
1. js
打包在js
文件夹里。
js
output: {
path: path.resolve(__dirname, "./dist"), //生成目录
filename: "./js/[name].[contenthash:8].bundle.js", //打包生成的文件名
clean: true, //清空打包结果
},
2.css
打包在css
文件夹里。
js
plugins: [
new HtmlWebpackPlugin({ template: "index.html" }),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css",
}),
],
3. 图片、字体
打包在static
文件夹里。
js
{
test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
use: [
{
loader: "url-loader",
options: {
outputPath: "static",
esModule: false,
limit: 100 * 1024,
name: "[name].[contenthash:8].[ext]",
},
},
],
type: "javascript/auto",
},
这样,一个基本的vue + ts 的工程就搭建起来了🤣🤣🤣🤣。