用webpack4.0做更多事情
上一篇webpack入門文章中,我們學會了怎麼使用webpack搭建一個前端工程,瞭解了webpack的一些核心概念。但是webpack的功力遠不止如此,在本文中,我們將學習如何使用webpack來做更多的事情,如何進行環境分離,如何配置es6,再配置vue,使用vue來進行開發。
這篇文章是入門文章的延續,不太瞭解webpack的同學可以先從入門文章看起,循序漸進。
開發與生產環境的分離
在實際開發中,會有許多環境,有 開發環境,生產環境,測試環境,預發環境....(因公司而異)。最常見的兩種是開發環境和生產環境。在不同的環境會有很多不同的配置。所以我們需要把不同環境的配置檔案從webpack.config.js
檔案中分離出來。
首先進行目錄的改造。首先安裝依賴,用於融合配置檔案。
npm install -D webpack-merge
複製程式碼
webpack-demo
|- config
|- webpack.base.js
|- webpack.dev.js
|- webpack.pro.js
|- package.json
|- src
|- 略
複製程式碼
webpack.base.js
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: path.resolve(__dirname,'./src/index.js'),
},
output: {
filename: '[name].[hash].js',
path: path.resolve(__dirname,'../dist'),
},
module: {
rules:[
{
test: /\.css$/,
use: [
"style-loader",
"css-loader"
]
},{
test: /\.(png|svg|jpg|gif)$/,
use:{
loader:'url-loader',
options: {
limit: 8192,
name: 'images/[name].[ext]?[hash]'
}
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
title:'WebpackTest'
})
]
}
複製程式碼
output檔名修改: 我們需要對output的filename選項進行修改。在使用者訪問網頁之後,會載入dist包中的bundle.js,並且進行快取。在我們進行版本更新以後,如果載入檔名還是bundle.js的話。瀏覽器不會拉去新的bundle.js資源,會直接使用瀏覽器快取的資源。所以我們需要將每次打包後的資源名都命名不同。[name].[hash].js
會根據檔案內容給每個檔名加上唯一的雜湊,這樣就不會出現重名檔案了。
開發環境(dev)
webpack.dev.js
const merge = require("webpack-merge");
const base = require("./webpack.base");
const webpack = require("webpack");
module.exports = merge(base ,{
mode: 'development',
devtool: 'source-map',
devServer:{
compress: true, //啟用壓縮
port: 1207, //埠
open: false, //自動開啟瀏覽器
hot: true
},
plugins:[
new webpack.HotModuleReplacementPlugin()
]
})
複製程式碼
首先介紹一下開發環境下我們需要進行配置的幾點
- source-map:source-map在開發中的用處很大,在瀏覽器允許的程式碼是經過編譯以後的程式碼,在出現一些錯誤的時候,如果不使用source-map的時候,錯誤無法定位到原始碼中。使用了source-map以後,可以直接定位到錯誤出現的行。配置source-map只需要將devtool屬性配置為source-map就可以。
- devserver配置:devserver屬性可以對開發環境選項進行一些配置,比如:自動開啟瀏覽器,服務埠號,熱更替,是否壓縮等。
- 模組熱更替(HotModuleReplacementPlugin): 模組熱更替允許在更新各種模組的時候,無需完全重新整理頁面,這個功能在開發環境中非常實用。最簡單的應用場景,你在寫一些樣式的時候,需要自己配置一些資料上去,這時候你需要調整字型大小。使用了模組熱更替之後會頁面不用重新整理就可以看到效果,省去了重新配置資料。在開啟熱更替時,還需要對模組熱更替外掛進行配置,否則會報錯。
生產環境(pro)
const merge = require('webpack-merge');
const base = require("./webpack.base.js");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require("path");
module.exports = merge(base ,{
mode: 'production',
plugins: [
new CleanWebpackPlugin(['dist'],{
root: path.resolve(__dirname,'../'),
})
],
})
複製程式碼
- clean-webpack-plugin:用於刪除檔案,在每次打包時,dist資料夾都會出現新的檔案,如果不進行刪除處理的話,會一直累加到dist資料夾裡面。所以這裡使用clean-webpack-plugin外掛,每次打包的時候都會先刪除之前的dist檔案。
模式(mode)
在入門篇中,我們每次編譯後都會出現he 'mode' option has not been set
的警告。這是webpack4新增的mode屬性,有兩種mode,development和production.
- development模式:
- 將
process.env.NODE_ENV
的值設為 development,過去需要通過webpack.DefinePlugin進行配置。 - 提供註釋、開發階段的詳細錯誤日誌和提示。
- 將
- production模式:
- 將
process.env.NODE_ENV
的值設為 production,過去需要通過webpack.DefinePlugin進行配置。 - 開啟所有的優化程式碼,壓縮外掛UglifyJsPlugin,過去需要自行配置。
- 去掉一些只在開發中執行的程式碼。
- 將
process.env.NODE_ENV
值用於再開發中進行環境判斷。
package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config config/webpack.dev.js",
"build": "webpack --config config/webpack.pro.js"
},
複製程式碼
再對npm script進行修改,指定對應配置檔案。
es6配置
下面我們進行es6的配置,由於es6未被所有瀏覽器全面支援,所有我們在使用的時候還想需要將其轉換為es5.主要用到的工具是babel,先進行babel依賴的安裝。
npm i -D @babel/core @babel/plugin-transform-runtime @babel/preset-env babel-loader
複製程式碼
webpack.base.js
...略
module:{
rulse:[
...略
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
}
]
}
複製程式碼
配置loader,這裡的exclde選項用於忽略一些檔案(敲黑板),減少webpack的處理量。/node_modules/都是已經轉好的檔案。
新增.babelrc檔案
webpack-demo
|- config
|- 略
|- package.json
|- src
|- 略
|- .babelrc
複製程式碼
{
"presets": ["@babel/preset-env"],
"plugins": ["@babel/plugin-transform-runtime"]
}
複製程式碼
- presets(設定轉碼規則):過去需要進行規則集指定,現在使用
@babel/preset-env
搭配@babel/core
解決 - plugins(外掛):
transform-runtime
外掛表示不管瀏覽器是否支援ES6,只要是ES6的語法,它都會進行轉碼成ES5
resolve
這些選項能設定模組如何被解析。在vue開發中通常使用的@/xxx/xxx
就是將@符號配置為src目錄。這樣webpack就能快速的找到該路徑,這樣的配置不僅可以方便開發,而且可以優化構建時間,減輕webpack的工作量。另外還可以配置字尾名的自動補全。
resolve: {
extensions: [ '.js', '.vue', '.scss', '.css'], //字尾名自動補全
alias: { //別名
'@': path.resolve(__dirname, '../src'),
}
},
複製程式碼
vue配置
最後我們進行vue的配置,先安裝依賴。
npm i -D vue vue-loader vue-style-loader vue-template-compiler
複製程式碼
- vue-loader是vue的loader,vue檔案是一個SFC類檔案,vue-loader會將其解析成為三部分,template部分用於渲染檢視,js,style。
- vue-style-loader用於處理vue-loader解析後的style.
- vue-template-compiler用於處理解析解析後的template.
先進行目錄改造
webpack-demo
|- config
|- 略
|- package.json
|- src
|- components
|- HelloWorld.vue
|- views
|- App.vue
|- asset
|- img.png
|- style.css
|- index.html
|- index.js
|- .babelrc
|- package.json
複製程式碼
webpack.base.js
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
module.exports = {
...略
module:{
rules:[
{
test: /\.css$/,
use: [
"style-loader",
"vue-style-loader",
"css-loader"
]
},{
test: /\.(png|svg|jpg|gif)$/,
use:'url-loader',
},{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},{
test:/\.vue$/,
use: 'vue-loader'
}
]
},
plugins:[
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
filename: './index.html', //檔名
template: './src/index.html', //模板檔案
})
]
}
複製程式碼
在這裡我們還需要安裝VueLoaderPlugin(),並且需要進行HtmlWebpackPlugin的重新配置,我們需要使用自己的template,因為必須建立一個div入口,將vue例項掛載在這上面。按原來方式使用該外掛的話,無法建立div入口。
index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpackStudy</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
複製程式碼
index.js
import Vue from 'vue'
import App from './views/APP'
import '@/asset/style'
new Vue({
el:'#root',
render: h => h(App)
})
複製程式碼
HelloWorld.vue
<template>
<div>
<img src="../asset/img.png" alt="">
<p>一起學習前端吧</p>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
p{
font-size: 50px;
}
</style>
複製程式碼
App.vue
<template>
<div id="app">
<hello-world></hello-world>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld'
export default {
name: "App",
components: {
HelloWorld
}
};
</script>
複製程式碼
- index.js依舊是我們的webpack入口檔案,我們將css檔案和APP.vue入口檔案引入,進行vue例項化,掛載在root節點上(index.html檔案的root節點)。
- 然後就可以開始元件開發啦。
小工具
當我們的元件躲起來了以後,webpack 打包非常耗時,我們來安裝一個ProgressBarPlugin
來檢視打包進度。
npm i -D progress-bar-webpack-plugin
複製程式碼
plugins:[
new ProgressBarPlugin()//打包進度條
]
複製程式碼
github
原始碼在我的github倉庫step2分支,希望能夠幫助到大家。
END
webpack這個技能棧將會是前端工程師必備的,對於小白來說,剛開始可能會不太好理解,其實不用把他看到太難,就是檔案從哪來到哪裡去的一個打包工具而已,我們所做的只是把他的各個模組的從哪來到哪去的問題配好,將每一部分都弄懂。接下來需要做的就是在此基礎上進行開發了。