写在前面
Webpack作为现在前端最流行的构建工具,可谓是每个前端码农的必修课。但是,现在的响应式框架(笔者用的最多的是Vue)基本都会对webpack做一定程度的封装,导致现在很多日常开发过程中根本使用不到webpack。
出于对webpack的好奇和渴望,所以想借着项目搭建的契机学习一下。而我又想到既然vue-cli可以封装webpack,那么自己是不是可以通过学习,自定义一个cli呢?所以有了这个系列。
那么,就请大家跟我一起探索一下webpack吧。
项目初步创建
起初刚开始接触的时候,我就疑惑了:webpack是管理项目构建的,如果自己创建项目该怎么搞来呢,因为我们都知道vue项目的创建可以使用cli创建一个模板工程。
最后还是官网给出了答案。
创建项目目录
在想创建项目的目录下,新建 webpack-vue 文件夹
mkdir webpack-vue
而我们的webpack是依赖nodejs的,那么就可以npm管理依赖包,所以进入项目目录,初始化npm
cd webpack-vue
npm init -y
此时项目目录会生成package.json文件,用于管理我们的依赖,文件内容如下:
{
"name": "webpack-vue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
下面就可以安装webpack的依赖了,终端运行代码:
npm install webpack webpack-cli --save-dev
因为这个项目webpack仅用于本地构建,所以只安装于开发环境。这里同时还安装了webpack-cli有些基础的配置。
此时package.json文件内容如下:
{
"name": "webpack-vue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2"
}
}
是不是跟我们vue项目中安装依赖以后的效果一样的,这其实都是npm做的工作(ps:当年刚学vue的时候以为这些依赖都是vue在管理,笑cry)。
创建代码目录
因为我们要做一个单页面应用,所以必须得有一个html文件,所以在项目目录下面创建 index.html 文件。
同时,正常的vue工程代码和静态资源等都是放在src目录下,所以我们在项目创建src目录
mkdir src
并在src目录下面创建 main.js。
最后工程目录暂时入下图:
webpack初步配置
新版本的webpack提供简单的默认配置,小型的项目只需要遵从相关规则就可以实现项目构建。但是,想要做些压缩、优化的工作,就必须依靠自定义配置了。
首先我们在项目根目录下创建文件 webpack.config.js,内容如下:
const path = require('path');
module.exports = {
entry: './src/main.js', //入口模块,会根据模块依赖关系,建立依赖图
output: { //输出位置、名称
filename: 'app.js',
path: path.resolve(__dirname, 'dist'),
},
};
其中把我们上一步创建的main.js设置为构建入口,webpack会从它开始一步步跟踪依赖关系,知道把所有依赖的模块都编译完成。
这时候就运行一下构建,在项目目录下终端运行:
npx webpack
运行后项目目录下会生成dist文件夹,里面会有一个app.js文件(由于mian.js什么都没写,所以输出的app.js也是空的):
这里会有有个疑问:构建出来的文件只有js,根本没用html页面。
HtmlWebpackPlugin
针对上面的问题,我们需要用到HtmlWebpackPlugin这个插件,首先安装插件:
npm install --save-dev html-webpack-plugin
然后在webpack.config.js文件引用并配置插件(plugins),修改后内容如下:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js', //入口模块,会根据模块依赖关系,建立依赖图
plugins: [
new HtmlWebpackPlugin({
title: '生成index.html',
}),
],
output: { //输出位置、名称
filename: 'app.js',
path: path.resolve(__dirname, 'dist'),
},
};
然后再运行构建 (npx webpack),结果如下:
可以看到不但完成了html基本的几个标签的填充(此时我们自己的index.html是没有内容的),还自动引用了我们构建出来的app.js文件(是不是很像vue项目最后的输出了,有点那味了)。
Vue安装
项目目录下运行(以vue2.0版本为例):
npm install vue@^2.6.0
然后在项目目录下面创建App.vue作为根模板,文件内容如下:
<template>
<div id="app">
我的Vue
</div>
</template>
<script>
export default {
name: "app",
data() {
return {};
},
watch: {},
created() {
},
methods: {},
computed: {}
};
</script>
这个时候我们可以运行一下构建命令,可以看到app.js里面内容还是空的,因为我们只是创建了App.vue,而并没有引用和挂载它。
所以在main.js更新代码如下:
import Vue from "vue";
import App from "./App.vue";
new Vue({
render: (h) => h(App),
}).$mount("#app");
这段代码的意思大概是创建一个Vue示例并引用App.vue内容,然后使用id=app的dom来加载。所以我们得修改index.html的内容:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
这是用我们运行构建,不出意外报错了:
提示我们没有对应的loaders,查阅资料后发现webpack想要把vue文件内容转换成js,需要配置vue-loader告诉它怎么做。
所以我们安装vue-loader:
npm install vue-loader@15 -D
npm install vue-template-compiler -D (版本必须保证和vue版本一直)
然后配置webpack.config.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {VueLoaderPlugin} = require("vue-loader");
module.exports = {
entry: "./src/main.js", //入口模块,会根据模块依赖关系,建立依赖图
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "生成index.html",
template:"./index.html"
}),
new VueLoaderPlugin()
],
output: {
//输出位置、名称
filename: "app.js",
path: path.resolve(__dirname, "dist"),
},
};
这里 new HtmlWebpackPlugin 时指定了本地的模板文件,构建时会根据模板文件内容生成输出的index.html。
然后增加了一个loader和一个plugins,这里有具体vue-loader的说明,就不做过多解释了:
https://vue-loader.vuejs.org/zh/
配置后执行构建命令,输出的dist/inde.html内容如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script defer="defer" src="app.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
浏览器打开后内容,为App.vue里我们编辑的内容:
至此,Vue项目的初步构建已经完成了。
下一篇会通过实例,来详细讲讲loader的使用和优化。