本文针对的面试题:
- 是否手动搭建过 vue 项目?
- webpack 的基础配置了解?
最近身边好几位不同岗位的同事跳槽了,所以我也来复习(学习)一下项目搭建相关知识,让自己不要这么焦虑。
基于: vue2 & webpack5
来吧,手动搭建起来。
初始化项目
选择一个目录初始化项目
mkdir dashboard
cd dashboard
npm init
执行以上命令,根据提示初始化项目,在 dashboard 目录下会自动创建一个 package.json 文件。 像下面这样:
{
"name": "dashbord",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "lucky",
"license": "ISC"
}
引入 webpack
npm install webpack webpack-cli -D
执行以上命令会自动生成 node_module 目录及 package-lock.json 文件,并下载 webpack、webpack-cli 的包。 现在的目录结构是这样:
> node_module
package-lock.json
package.json
添加 gitignore 文件
在根目录下添加.gitignore 文件,设置 node_modules 文件夹不上传
node_modules/
webpack 基础配置
在根目录下新建 webapck 目录,创建 webpack.config.js 文件
touch webpack.config.js
webpack 的核心思想就是打包,将一切 js 以外的文件打包为 js 可以使用的文件。配置 webpack 的入口、出口、插件、模块
const path = require("path");
module.exports = {
mode: "development", // 根据环境使用相应的内置优化
entry: "/src/index.js", // 入口文件
output: {
// 出口文件
filename: "bundle.js",
path: path.resolve(__dirname, "../dist"),
publicPath: "/",
},
plugins: [], // 使用的插件
module: {
generator: {}, // 生成器
parser: {}, // 解析器
rules: [], // 修改模块的创建方式
}, // 模块加载方案
};
别忘了执行 npm i path
测试 webpack 打包
现在我们新建一个 index.js 文件
const a = { x: 1 };
console.log("测试打包!", a);
然后在命令行执行 webpack
webapck ./index.js
可以看到,在根目录下生成了一个 dist 目录,在 dist 目录下生成了我们指定的出口文件 bundle.js :
console.log("测试打包!", { x: 1 });
现在我们引入了 webpack 也能够正常打包了,下一步是配置文件打包到 html 中。
测试将代码打包至 html 文件中
先在根目录下生成一个 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></body>
</html>
要做到将 js、css 等代码打包到 html 文件中,我们需要用到 htmlWebpackPlugin。 html-webpack-plugin 的作用是:当使用 webpack 打包时,创建一个 html 文件,并把 webpack 打包后的静态文件自动插入到这个 html 文件当中。 在命令行执行以下命令,安装插件:
npm install html-webpack-plugin --save-dev
在 webpack.config.js 文件中引入以上插件:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
title: "Vue -> Web App",
minify: {
collapseWhitespace: true, // 去掉空格
removeComments: true, // 去掉注释
},
}),
],
};
在命令行执行 webpack 命令:
webpack ./index.js --config ./webpack/webpack.config.js
现在根目录下自动生成了 dist 目录:
dist
budle.js
index.html
bundle.js:
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => {
// webpackBootstrap
/******/ var __webpack_modules__ = {
/***/ "./index.js":
/*!******************!*\
!*** ./index.js ***!
\******************/
/***/ () => {
eval(
"const a = {x: 1};\nconsole.log('测试打包!', a);\n\n\n//# sourceURL=webpack:///./index.js?"
);
/***/
},
/******/
};
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = {};
/******/ __webpack_modules__["./index.js"]();
/******/
/******/
})();
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" />
<title>Document</title>
<!-- 注意这里 -->
<script defer="defer" src="/bundle.js"></script>
</head>
<body></body>
</html>
观察以上代码,html 中自动插入了一个 script,其中引入了我们 index.js 打包后的代码。
到这里我们就完成了 webpack 打包的一个架子,但是日常开发我们还会使用 vue、react 等前端框架和 UI 框架,我们会在后面引入。
配置 npm run build
好的,为了后面测试方便,我们先在 package.json 中配置一个 build 自定义命令:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack ./src/index.js --config ./../webpack/webpack.config.js"
},
使用时直接 npm run build 就可以打包了。
引入 vue
- 引入 vue vue 可以在 script 中引入,这里我们使用 npm 方式引入:
npm i vue
vue 是一个前端框架,它的两个核心思想就是:双向数据绑定、组件化。 在 src 目录下先新建一个 App.vue 文件
<template>
<div>这是一个vue文件</div>
</template>
修改 html 文件
<body>
<div id="app"></div>
</body>
修改 index.js:
import Vue from "vue";
import App from "./App.vue";
new Vue({
el: "#app",
render: (h) => h(App),
});
现在我们执行 npm run build 肯定是不行的,因为 webpack 还不能识别 vue 后缀的文件。需要先安装 vue-loader:
npm i vue-loader --save-dev
npm i cache-loader --save-dev
npm i thread-loader --save-dev
cache-loader 的作用: 在一些性能开销较大的 loader 之前添加 cache-loader,以便将结果缓存到磁盘里。
thread-loader 的作用:
把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker 池(worker pool)中运行
修改 webpack.config.js:
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
plugins: [new VueLoaderPlugin()],
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: "cache-loader",
},
{
loader: "thread-loader",
},
{
loader: "vue-loader",
options: {
compilerOptions: {
preserveWhitespace: false,
},
},
},
],
exclude: /node_modules/,
},
],
},
};
安装 vue-template-compiler 和 html-loader
npm i vue-template-compiler --save-dev
npm i html-loader --save-dev
现在执行 npm run build 打包后的文件用 node.js 静态服务跑起来可以看到我们 vue 组件中的 "这是一个 vue 文件" 字样。
配置 devServer
用 nodejs 来跑静态文件比较麻烦,现在我们配置 webapck 自带的开发工具 webpack devServer
npm install webpack-dev-server -D
在 webpack.config.js 中启用 devServer:
module.exports = {
devServer: {
port: 3005, // 启动端口
hot: true, // 是否开启热模块替换
open: true, // 是否开启自动打开页面
proxy: {
// 代理规则
"/api": {
target: "http://123.123.123.123:8080",
secure: false,
changeOrigin: true,
pathRewrite: {
// 重定向规则
"^/api": "/api",
},
},
},
},
};
在 shell 中新增命令 dev:
"dev": "webpack-dev-server --config ./webpack/webpack.config.js",
执行 npm run dev 项目在 http://localhost:3005 启动。注意如果端口占用了就换一个端口启动。 到这里我们就完成了一个 webpack 手动配置 vue 项目的基础框架了。接下来开始开发。这里我选择的是 vue 的好搭档 element-ui 来开发。
引入 element-ui
在命令行执行:
npm i element-ui -D
修改 index.js:
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
Vue.use(ElementUI);
这里我们引入了 element-ui 的 css 文件,所以要先添加 css-loader:
npm i style-loader css-loader -D
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
};
在 App.vue 中添加一个 el-button 测试一下:
<el-button type="primary">你好element-ui</el-button>
现在我们重启服务,可以看到页面上已经展示了这个蓝色(element-ui 默认的颜色)的按钮。开心~!
支持 scss
npm i css-loader style-loader sass sass-loader -D
在 webpack.config.js 文件中添加的 rules,
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
修改 ui 主题颜色
Element 的 theme-chalk 使用 SCSS 编写,如果你的项目也使用了 SCSS,那么可以直接在项目中改变 Element 的样式变量。新建一个样式文件,例如 element-variables.scss
/* 改变主题色变量 */
$--color-primary: teal;
/* 改变 icon 字体路径变量,必需 */
$--font-path: "~element-ui/lib/theme-chalk/fonts";
@import "~element-ui/packages/theme-chalk/src/index";
修改 index.js
// import "element-ui/lib/theme-chalk/index.css";
import "./element-variables.scss";
完成以后,界面上按钮的蓝色背景就切换成了绿茶色了。 后面我们就可以使用 element-ui 开始开发 crm 系统界面啦!
支持 ES6 语法
在app.vue中添加测试代码:
<script>
export default {
async created(){
const timeout = function(time){
return new Promise(resolve => {
setTimeout(resolve, time);
})
};
console.log('11111');
await timeout(3000);
console.log('22222');
},
}
</script>
保存以后,发现报错,原因是我们的webpack不支持ES6。 修改 webpack.config.js,添加 rules
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-modules-commonjs',
],
},
},
exclude: /node_modules/,
},
配置 nginx
这个项目部署我采用的 nginx 代理的方式:
access_log /dev/stdout;
server {
listen 80 default_server;
location / {
root /app/dist;
try_files $uri $uri/ /index.html;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ( !-f $request_filename ) {
rewrite ^/(.*) /index.html break;
}
if ($request_method = 'OPTIONS') {
return 204;
}
}
location /service-name/ {
proxy_pass http://service-name:8080/;
index index.html index.htm;
}
}
根据 nginx 的文档,配置一个服务的正向代理没有什么问题,配置反向代理也很简单。不过这里我遇到一个区分不同环境的问题:不同的环境访问的后端的服务地址不同,需要动态配置。这里我采用的是直接配置成 ranchers 集群内的服务名称的方式。
开启 gzip 压缩
gzip 可以在 http 段加也可以在 server 段加。
http {
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
}
总结
这篇文章包含的内容有:webpack 打包配置、识别 vue 文件、配置 devServer、element-ui、nginx 部署、gzip 配置。基础的框架已经有了,开发过程中再遇到需要的插件和loader再自行安装就好啦!
文章到这里就告一个段落了,以上步骤已经放到github上了,如果大家想看一个 CRM 系统开发框架搭建后续的内容,可以在评论区留言。
tips
以前新建 vue 项目都是 cli 工具,对搭建流程不太了解。 就在今年年初的时候,还一直很恐惧使用 webpack 自己搭建项目,随着最近 2 个多月的新项目搭建和部署上手,现在已经一点都不怕啦。 虽然还有很多不会的知识,但是,只要相信自己,并且勇敢踏出第一步,没有什么问题是不能解决的,大家一起加油呀!欢迎批评指正,喵!