webpack 是一個前端工程化打包工具,對於前端工程師來說 webpack 是一項十分重要的技能。下面我們就通過搭建一個 vue 專案來學習使用 webpack
主要環境:
- node v14.15.0
- npm v6.14.9
- webpack v5.10.0
- webpack-cli v4.2.0
- vue v2.6.12
本專案實現以下功能:
- 與
vue/cli
類似的基本目錄 - 支援
*.vue
,*.css
等檔案 - 支援
es6
及以上語法 - 支援載入圖片
- 熱載入
構建專案基本目錄
執行npm init
並建立以下目錄
demo
├─ dist
├─ public
└─ src
安裝必要依賴
webpack 及相關外掛
- webpack
npm install -D webpack webpack-cli
- webpack 本地伺服器外掛
npm install -D webpack-dev-server
- html 生成外掛,它會將生成的 js 和 css 檔案插入到 html 中
npm install -D html-webpack-plugin
- vue 外掛
npm install -D vue-loader vue-template-compiler
- css 外掛
npm install -D css-loader style-loader
- 圖片外掛
npm install -D file-loader url-loader
- babel 外掛
npm install -D @babel/core @babel/cli @babel/preset-env babel-loader
,npm install @babel/polyfill
安裝 vue
npm install vue vue-router
搭建專案
簡單實現 webpack 打包
新建src/main.js
,並寫入:
console.log('Hello Webpack');
根目錄下新建webpack.config.js
,並寫入:
const path = require('path');
const config = {
entry: './src/main.js', // 定義入口檔案
output: {
path: path.resolve(__dirname + '/dist'), // 打包生成檔案地址,必須是絕對路徑
filename: '[name].build.js', // 生成的檔名
},
};
module.exports = config;
在package.json
中的scripts
中新增一個指令碼:
{
...
"scripts": {
"build": "webpack --mode=production"
}
...
}
在命令列中執行npm run build
,此時專案目錄中出現了dist/main.build.js
,證明執行成功
js 檔案打包成功後,需要一個 html 檔案來引入這個 js 檔案,這就需要用到我們一開始下載的html-webpack-plugin
首先新建public/index.html
建立一個基礎頁面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webpack搭建vue</title>
</head>
<body>
<!-- 如果瀏覽器禁止載入js指令碼 -->
<noscript>
<strong>
We're sorry but this site doesn't work properly without JavaScript
enabled. Please enable it to continue.
</strong>
</noscript>
<div id="app"></div>
<!-- build後的檔案會在這之後自動引入 -->
</body>
</html>
在public
下隨便放入一個圖示favicon.ico
,然後在webpack.config.js
中配置外掛:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
...
plugins:[
new HtmlWebpackPlugin({
filename: 'index.html', // 生成的資料夾名
template: 'public/index.html', // 模板html
favicon: 'public/favicon.ico', // 圖示
}),
]
}
...
之後再次執行npm run build
,dist
下會生成index.html
,favicon.ico
,main.build.js
三個檔案,通過瀏覽器開啟index.html
,就可以發現控制檯輸出了Hello Webpack
,頁面圖示也變成了自己設定的圖示,通過編輯器開啟index.html
,我們會發現 webpack 幫助我們自動引入了favicon.ico
和main.build.js
:
<!DOCTYPE html>
<html>
<head>
...
<link rel="icon" href="favicon.ico" />
</head>
<body>
...
<script src="main.build.js"></script>
</body>
</html>
開啟熱載入
webpack 熱載入需要用到webpack-dev-server
,在開始我們已經安裝過了,在webpack.config.js
中配置:
const config = {
...
devServer: {
contentBase: path.join(__dirname, 'dist'), // html所在路徑
compress: true, // 是否壓縮
port: 3000, // 埠
hot: true, // 熱部署
open: true, // 打包完成後自動開啟網頁
}
}
增加package.json
指令碼:
{
...
"scripts": {
"build": "webpack --mode=production",
"serve": "webpack serve"
}
...
}
執行npm run serve
,打包成功後會自動開啟網頁,並且當你修改src/main.js
或src/index.html
的內容的時候,瀏覽器會自動重新打包並重新整理
配置 Vue
讓 webpack 打包*.vue
檔案需要vue-loader
和vue-template-compiler
,同時為了 webpack 能夠解析 vue 中的 css 還需要用到css-loader
和vue-style-loader
,在webpack.config.js
配置以上外掛:
...
const { VueLoaderPlugin } = require('vue-loader');
const config = {
...
// loaders
module: {
rules: [
{
// *.vue
test: /\.vue$/,
loader: 'vue-loader',
},
{
// `*.vue` 檔案中的 `<style>` 塊以及普通的`*.css`
test: /\.css$/,
use: ['vue-style-loader', 'css-loader'],
},
],
},
plugins: [
...
new VueLoaderPlugin(),
],
...
};
...
配置完後新建src/App.vue
:
<template>
<div class="example">
{{ msg }}
</div>
</template>
<script>
export default {
data() {
return {
msg: 'Hello Webpack',
};
},
};
</script>
<style>
.example {
color: red;
}
</style>
修改src/main.js
:
import Vue from 'vue';
import App from './App.vue';
new Vue({
el: '#app',
render: (h) => h(App),
});
然後執行npm run serve
,即可看到頁面上顯示的Hello Webpack
配置圖片資源的載入
使用file-loader
或url-loader
載入,它們都是用於打包檔案和圖片資源的,區別在於url-loader
封裝了file-loader
在訪問網站時如果圖片較多,會發很多 http 請求,會降低頁面效能。這個問題可以通過 url-loader
解決。url-loader
會將引入的圖片編碼,生成 dataURl。相當於把圖片資料翻譯成一串字元,再把這串字元打包到檔案中,最終只需要引入這個檔案就能訪問圖片了。
當然,如果圖片較大,編碼會消耗效能。因此 url-loader
提供了一個 limit 引數,小於 limit 位元組的檔案會被轉為 DataURl,大於 limit 的還會使用 file-loader 進行 copy。
此處我們使用 url-loader
,由於它是基於 file-loader
的封裝,所以也需要引入 file-loader
。
...
const config = {
...
module: {
rules: [
...
{
// 圖片
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 25000,
},
},
},
],
},
};
...
然後新增一個圖片src/assets/logo.png
,在App.vue
中引入:
<template>
<div class="example">
{{ msg }}
<img :src="url" />
</div>
</template>
<script>
import logo from './assets/logo.png';
export default {
data() {
return {
msg: 'Hello Vue1',
url: logo,
};
},
};
</script>
<style>
.example {
color: red;
}
</style>
再次npm run serve
即可看到圖片
配置 babel
babel 可以將 js 的高版本(es6)語法轉換為低版本,使得專案相容低版本瀏覽器
需要我們注意的是,babel7 與 babel6 不相容,因此需要使用最新版本的 babel 和 babel 外掛,在前面文章開始我們已經安裝了 babel7 版本的 babel 外掛,下面我們在webpack.config.js
中配置它:
...
const config = {
...
module: {
rules: [
...
{
// *.js
test: /\.js$/,
exclude: /node_modules/, // 不編譯node_modules下的檔案
loader: 'babel-loader',
},
],
},
};
...
配置完後在專案根目錄下建立一個 babel 的配置檔案.babelrc
,寫入如下內容:
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
更多 babel 配置請檢視babel 中文官網
配置完成後新建一個src/utils/getData.js
測試一下:
export default function getData() {
return new Promise((resolve, reject) => {
resolve('ok');
});
}
在src/App.vue
中引入:
<template>
<div class="example">
{{ msg }}
<img :src="url" />
</div>
</template>
<script>
import logo from './assets/logo.png';
import getData from './utils/getData';
export default {
data() {
return {
msg: 'Hello Vue1',
url: logo,
};
},
methods: {
async fetchData() {
const data = await getData();
this.msg = data;
},
},
created() {
this.fetchData();
},
};
</script>
<style>
.example {
color: red;
}
</style>
重新執行npm run serve
後,頁面顯示ok
,babel 引入成功
設定 src 別名以及省略字尾
為了方便開發,我們可以給 src 目錄設定別名,以及將常用檔案型別的字尾省略
...
const config = {
...
// 解析路徑
resolve: {
// 設定src別名
alias: {
'@': path.resolve(__dirname, 'src'),
},
//字尾名 可以根據需要自由增減
extensions: ['.js', '.vue'],
},
...
};
...
這樣我們就可以以如下方式匯入 vue 和 js 檔案:
// 匯入App.vue
import App from '@/App';
// 匯入getData
import getData from '@/utils/getData';
至此,我們已經簡單的搭建出了 vue 專案,在專案中我們可能還會需要用到less
,sass
,字型圖示等工具,針對這類工具 webpack 都有與其對應的loader
或plugin
,需要時搜尋他們的文件即可。
- 本專案倉庫 Tuzilow/webpack-vue