基礎常識:
查看版本號:
vue -V
webpack -v 查看當前版本
已有項目升級webpack到最新版:
刪除node_modules目錄
進入package.json文件修改版本號到最新
npm install --save-dev webpack
升級webpack到最新版:
刪除node_modules目錄
npm install --save-dev webpack
npm -v/cnpm -v
簡介:此項目為vue2.x 使用webpack4構建項目的文檔教程暇务,自我學習保存具壮。
前言:為了方便項目的存儲奏瞬,可以先在碼云上建個倉庫吸祟,git clone一下琉历,然后修改下.gitignore文件 將node_modules/ 和 /dist/ 加入舞萄,最好從其他項目中復制一份過來恩沽。
好了誊稚,正文開始:
1.npm init 生成 packge.json文件
2.安裝必要依賴
(1)npm i webpack webpack-cli webpack-dev-server webpack-merge --save-dev
webpack-cli: webpack中分離出來的
webpack-dev-server
webpack-merge
(2)npm i vue vue-router vuex --save
3.創(chuàng)建目錄結構
|--dist
|--build
|--webpack.prod.js
|--webpack.dev.js
|--webpack.base.js
|--src
|--index.js
|--app.vue
|--router.js
|--store.js
|--assets
|--components
|--views
|--index.html
4.安裝vue核心解析插件 npm i vue-loader vue-template-compiler --save-dev
5.安裝其他的loader
在同一個 test 下配置多個loader時,優(yōu)先處理的 loader 放在配置數(shù)組的后面
(1)必要的:
CSS 基礎 loader:
css-loader: "^1.0.0", // 加載.css文件
style-loader: "^0.21.0", //使用<style>將css-loader內(nèi)部樣式注入到我們的HTML頁面
file-loader// 解析圖片罗心,字體等
url-loader //設置上limit選項里伯,將小于limit的圖片轉編碼,大于limit的交給file-loader復制路徑來引用使用
注意:具體參考vue-webpack模板协屡,配置url-loader后不需要配置file-loader俏脊,但可在url-loader中添加name字段,file-loader會實現(xiàn)name字段內(nèi)容肤晓。文末會放上build文件夾下爷贫,三個配置文件的代碼。
npm i babel-core --save-dev
npm i @babel/core --save-dev
@babel/preset-env --save-dev // 是一個配置文件补憾,我們可以使用這個配置文件轉換 ES2015/ES2016/ES2017 到 ES5
babel-preset-env 這個是舊版本的
.babelrc文件:
{
"presets": ["@babel/preset-env"]
}
npm i babel-loader --save-dev //可以把ES6語法轉為ES5語法
npm i html-webpack-plugin --save-dev //安裝 html 模板解析插件
npm i clean-webpack-plugin --save-dev //解決每次重新打包漫萄,dist 文件夾文件未清除
(2)選擇性的:
CSS 前處理 less 兩件套
"less": "^3.8.0",
"less-loader": "^4.1.0",
CSS 前處理 sass 兩件套
"node-sass": "^4.9.2",
"sass-loader": "^7.1.0",
CSS 后處理 postcss 兩件套
"postcss-loader": "^2.1.6",
"autoprefixer": "^9.1.0",
npm install mini-css-extract-plugin --save-dev //webpack4中分離CSS。插件來分離 css盈匾。
注意:這個插件應該只用在 production 配置中腾务,并且在loaders鏈中不使用 style-loader, 特別是在開發(fā)中使用HMR,因為這個插件暫時不支持HMR,具體看模板文件配置
npm install image-webpack-loader --save-dev //圖片壓縮
npm i optimize-css-assets-webpack-plugin --save-dev // css代碼壓縮削饵,優(yōu)化css結構岩瘦,利于網(wǎng)頁加載和渲染
npm i uglifyjs-webpack-plugin --save-dev // js代碼壓縮
npm i --save-dev cross-env 能跨平臺地設置及使用環(huán)境變量,不同平臺使用唯一指令窿撬,無需擔心跨平臺問題启昧。
總結一下loader的常用四種寫法:
use: [xxx, xxx]
use: [{loader: XXX}, {loader: XXX}]
use: [{
loader: XXX,
options: {}
}, 'XXX']
loader: [XXX, XXX]
loader的options配置項里面還可以放置loader,also plugins
常用的loader:
- 處理樣式的:style-loader,css-loader,postcss-loader,sass-loader,less-loder
- 處理es6的:babel-loader(要連同babel-core, babel-preset-env)一起用
- 處理圖片的:file-loader, url-loader, image-webpack-loader
常用的plugin:
- 壓縮js:uglifyjs-webpack-plugin
- 合并&壓縮css: mini-css-extract-plugin劈伴,optimize-css-assets-webpack-plugin
- 清除目錄:clean-webpack-plugin
- 生成html:html-webpack-plugin
- postcss相關的:postcss-plugin-px2rem密末,postcss-preset-env,postcss-sprites跛璧,autoprefixer
- webpack自帶的方法:webpack.ProvidePlugin等
build文件夾下的配置文件:
webpack.base.js
// webpack.base.js
// 存放 dev 和 prod 通用配置
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
//mini-css-extract-plugin插件應該只用在 production 配置中严里,并且在loaders鏈中不使用 style-loader, 特別是在開發(fā)中使用HMR,因為這個插件暫時不支持HMR
const devMode = process.env.NODE_ENV !== 'production';
//console.log(process.env.NODE_ENV,"devMode--------------")
//webpack4 分離css插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
//使用 WEBPACK_SERVE 環(huán)境變量檢測當前是否是在 webpack-server 啟動的開發(fā)環(huán)境中
//const dev = Boolean(process.env.WEBPACK_SERVE)
// 使用happypack---加速webpack打包
const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({
size: os.cpus().length
});
module.exports = {
entry: './src/index.js', //入口
/*
配置各種類型文件的加載器追城,稱之為 loader
webpack 當遇到 import ... 時刹碾,會調(diào)用這里配置的 loader 對引用的文件進行編譯
*/
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
// 正則匹配所有以.css結尾的文件
// 它會應用到普通的 `.css` 文件
// 以及 `.vue` 文件中的 `<style>` 塊
test: /\.(sa|sc|c)ss$/,
// 使用css-loader和style-loader依次對css文件進行處理
/*
先使用 css-loader 處理,返回的結果交給 style-loader 處理座柱。
css-loader 將 css 內(nèi)容存為 js 字符串教硫,并且會把 background,
@font-face 等引用的圖片叨吮,字體文件交給指定的 loader 打包,
*/
// 按照數(shù)組中從后往前的順序
use: [
devMode?'vue-style-loader':{
loader:MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
/***
**還沒有嘗試css-loader的url屬性是否可行
***/
/* {
loader: 'css-loader',
options: {
url: false, // css中加載圖片的路徑將不會被解析 不會改變
minimize: true, //
importLoaders: 1
}
}, */
'css-loader',
'sass-loader'
]
},
// 圖片處理
{
//test: /\.(gif|png|jpe?g|svg)$/i,
test: /\.(png|jpg|jpeg|gif|svg|svgz)(\?.+)?$/,
//enforce: 'pre', // 這會應用該 loader瞬矩,在其它之前
use: [
{
loader: 'url-loader',
options: {
limit: 8192, //單位Bytes茶鉴,即轉換8KB以下的圖
// 當圖片大于8192時,分離圖片至imgs文件夾
// [ext]是占位符 表示文件的后綴名
/* name: devMode ? "img/[name].[ext]" : "img/[hash:6][name].[ext]" */
name: devMode ? "[name].[ext]" : "[hash:6][name].[ext]",//和注釋那行的效果一樣
publicPath: "./img/",
outputPath: "img/"
/* fallback: ['file-loader','image-webpack-loader'],
quality: 85 */
}
},
// 圖片壓縮
//'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
optipng: {
enabled: false
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false
},
webp: {
quality: 75
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 8192,
name: devMode ? "fonts/[name].[ext]" : "fonts/[hash:3][name].[ext]"
}
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
/* exclude: __dirname + 'node_modules',
include: __dirname + 'src',
options: {
presets: ['env']
} */
},
{
test: /\.js$/,
//把對.js 的文件處理交給id為happyBabel 的HappyPack 的實例執(zhí)行
loader: 'happypack/loader?id=happyBabel',
//排除node_modules 目錄下的文件
exclude: /node_modules/
}
]
},
/*
配置 webpack 插件
plugin 和 loader 的區(qū)別是景用,loader 是在 import 時根據(jù)不同的文件名涵叮,匹配不同的 loader 對這個文件做處理,
而 plugin, 關注的不是文件的格式伞插,而是在編譯的各個階段割粮,會觸發(fā)不同的事件,讓你可以干預每個編譯階段媚污。
*/
plugins: [
/*
html-webpack-plugin 用來打包入口 html 文件
entry 配置的入口是 js 文件舀瓢,webpack 以 js 文件為入口,遇到 import, 用配置的 loader 加載引入文件
但作為瀏覽器打開的入口 html, 是引用入口 js 的文件耗美,它在整個編譯過程的外面京髓,
所以,我們需要 html-webpack-plugin 來打包作為入口的 html 文件
*/
new HtmlWebpackPlugin({
/*
template 參數(shù)指定入口 html 文件路徑商架,插件會把這個文件交給 webpack 去編譯堰怨,
webpack 按照正常流程,找到 loaders 中 test 條件匹配的 loader 來編譯蛇摸,那么這里 html-loader 就是匹配的 loader
html-loader 編譯后產(chǎn)生的字符串备图,會由 html-webpack-plugin 儲存為 html 文件到輸出目錄,默認文件名為 index.html
可以通過 filename 參數(shù)指定輸出的文件名
html-webpack-plugin 也可以不指定 template 參數(shù)赶袄,它會使用默認的 html 模板揽涮。
*/
template: path.resolve(__dirname, '../index.html'),
}),
new VueLoaderPlugin(),
//
new MiniCssExtractPlugin({
filename: devMode ? 'css/[name].css' : 'css/[name].[hash:5].css',
chunkFilename: devMode ? 'css/[id].css' : 'css/[id].[hash:5].css',
}),
// 解決vender后面的hash每次都改變
/*
使用文件路徑的 hash 作為 moduleId。
雖然我們使用 [chunkhash] 作為 chunk 的輸出名饿肺,但仍然不夠蒋困。
因為 chunk 內(nèi)部的每個 module 都有一個 id,webpack 默認使用遞增的數(shù)字作為 moduleId唬格。
如果引入了一個新文件或刪掉一個文件,可能會導致其他文件的 moduleId 也發(fā)生改變颜说,
那么受影響的 module 所在的 chunk 的 [chunkhash] 就會發(fā)生改變购岗,導致緩存失效。
因此使用文件路徑的 hash 作為 moduleId 來避免這個問題门粪。
*/
new webpack.HashedModuleIdsPlugin(),
//happyPack實例
new HappyPack({
//用id來標識 happypack處理那里類文件
id: 'happyBabel',
//如何處理 用法和loader 的配置一樣
loaders: [{
loader: 'babel-loader?cacheDirectory=true',
}],
//共享進程池
threadPool: happyThreadPool,
//允許 HappyPack 輸出日志
verbose: true,
//啟用debug 用于故障排查喊积。
debug: false
}),
//設置環(huán)境變量信息
new webpack.DefinePlugin({
//雞肋功能?
/* 'process.env':{
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
} */
})
] // 插件
};
webpack.dev.js
// webpack.dev.js
// 存放 dev 配置
const merge = require('webpack-merge');
const common = require('./webpack.base.js');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
devServer: { // 開發(fā)服務器
// dev-server 服務路徑
contentBase: path.join(__dirname, "dist"),
compress: true,
host: '0.0.0.0',
//host: 'localhost',
port: 8085,
// 自動打開瀏覽器
open: true,
// 啟動熱更新
hot: true,
// 顯示 webpack 構建進度
progress: true,
//重載腳本出現(xiàn)在包中,構建消息會出現(xiàn)在控制臺玄妈。
inline: true,
// 在頁面上全屏輸出報錯信息
overlay: {
warnings: true,
errors: true
},
clientLogLevel: 'warning',
// 可以進行接口代理配置
proxy: {
"/api": {
target: "http://erp.my012.com:8081",
//https會用到
secure: false
}
},
publicPath: '/'
},
output: { // 輸出
filename: 'js/[name].[hash].js', // 每次保存 hash 都變化
path: path.resolve(__dirname, '../dist')
},
module: {},
plugins: [
//命令行模式 --hot 將會自動添加此插件
//new webpack.HotModuleReplacementPlugin()
]
});
webpack.prod.js
// webpack.prod.js
// 存放 prod 配置
const path = require('path');
// 合并配置文件
const merge = require('webpack-merge');
const common = require('./webpack.base.js');
// 打包之前清除文件
const CleanWebpackPlugin = require('clean-webpack-plugin');
// 分離CSS插件
//const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 壓縮CSS和JS代碼
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
//const process.env.NODE_ENV = 'production'
module.exports = merge(common, {
module: {},
/*
webpack 執(zhí)行模式
development:開發(fā)環(huán)境乾吻,它會在配置文件中插入調(diào)試相關的選項髓梅,比如 moduleId 使用文件路徑方便調(diào)試
production:生產(chǎn)環(huán)境,webpack 會將代碼做壓縮等優(yōu)化
*/
mode: 'production',
devtool: 'cheap-module-source-map',
output: {
filename: 'js/[name].[contenthash].js', //contenthash 若文件內(nèi)容無變化绎签,則contenthash 名稱不變
// 打包輸出目錄
path: path.resolve(__dirname, '../dist')
},
plugins: [
new CleanWebpackPlugin(['dist/*'], {
root: path.resolve(__dirname, '../')
})
/* new MiniCssExtractPlugin({
filename: "css/[name].[hash].css",
chunkFilename: 'css/[id].[hash].css'
}) */
],
//分離不常變化的文件枯饿, 如 node_modules 下引用的庫---webpack中的字段
optimization: {
// 分離chunks
splitChunks: {
/*
默認 entry 的 chunk 不會被拆分
因為我們使用了 html-webpack-plugin 來動態(tài)插入 <script> 標簽,entry 被拆成多個 chunk 也能自動被插入到 html 中诡必,
所以我們可以配置成 all, 把 entry chunk 也拆分了
*/
chunks: 'all',
cacheGroups: {
common:{
/* chunks: "initial",
minChunks: 2,
maxInitialRequests: 5,
minSize: 10000 */
},
vendor: {
test: /[\\/]node_modules[\\/]/,
chunks: "initial", // 只打包初始時依賴的第三方
name: "vendor",
priority: 10
//enforce: true //
},
styles: {
/* name: 'style',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true */
}
}
},
/* runtimeChunk: {
name: "manifest"
}, */
minimizer: [
// 壓縮JS-- 自定義js優(yōu)化配置奢方,將會覆蓋默認配置
new UglifyJsPlugin({
exclude: /\.min\.js$/, // 過濾掉以".min.js"結尾的文件,我們認為這個后綴本身就是已經(jīng)壓縮好的代碼爸舒,沒必要進行二次壓縮
uglifyOptions: {
compress: {
warnings: true, // 去除警告
drop_debugger: true, // 去除debugger
drop_console: true // 去除console.log
}
},
cache: true, // 開啟緩存
parallel: true, // 平行壓縮,開啟并行壓縮蟋字,充分利用cpu
sourceMap: false, // set to true if you want JS source maps
extractComments: true // 移除注釋
}),
// 壓縮css
new OptimizeCSSAssetsPlugin({})
]
}
});