使用webpack搭建vue項目及注意事項
有一句話叫“前人栽樹后人乘涼”,還有一句話叫“如果說我看得比別人更遠些,那是因為我站在巨人的肩膀上”。前一句是國人的俗語,后一句是那個發(fā)現(xiàn)了“萬有引力”定律的牛頓說的。為什么要引用這兩句呢?是因為我剛開始用vue的時候,使用的是vue-cli來搭建vue項目,快速又好用;我剛開始用react的時候,使用的是create-react-app來搭建react項目,方便又省事。使用這些已有的腳手架來搭建項目,無可厚非,對于新手來說,也確實能快速構(gòu)建,不做置評。
既然已經(jīng)有了這些現(xiàn)成的腳手架了,為什么我們還熱衷于自己來配置webpack來搭建構(gòu)建項目呢?因為我們只有了解并學(xué)會了配置webpack,我們才能更好地在打包構(gòu)建項目時將webpack的性能發(fā)揮到極致,才能根據(jù)自身項目的實際需求,配置有利于項目開發(fā)的各種工具、插件,提高我們的開發(fā)效率。比如我們在打包項目時,可以分析哪些地方降低了webpack的打包速度,別人打包速度需要花去十多秒、二十多秒,而你能將打包的速度提升至幾秒,這就是你的優(yōu)勢。當(dāng)然,涉及到webpack的運行原理以及開發(fā)自己的loader或plugin就可以自行去學(xué)習(xí)了哈,本文只帶你配置一個webpack來搭建一個vue項目。
wepack作為一個“模塊打包機”其實是依賴了龐大的插件體系,插件體系是webpack的核心,可以說,webpack的生態(tài)就是建立在眾多插件之上的,而開發(fā)環(huán)境和生產(chǎn)打包環(huán)境依賴的插件還是有所不同的,先以開發(fā)環(huán)境為例
webpack.config.js:
const path = require('path');
const Webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const resolve = (dir) => {
return path.join(__dirname, '..', dir)
}
const assetsPath = (_path) => {
return path.join('static', _path)
}
const isEnvProduction = process.env.NODE_ENV == "production", port = 3003;
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: resolve('src'),
output: {
path: resolve('dist'),
filename: isEnvProduction ? assetsPath('js/[name]-[hash].js') : '[name]-[hash].js',
chunkFilename: isEnvProduction ? assetsPath('js/[name]-[chunkhash:5].min.js') : '[name]-[chunkhash:5].min.js',
publicPath: '/',
},
resolve: {
extensions: ['*', '.js', '.vue'], //webpack2.x extensions[0]不能為空 resolve屬性中的extensions數(shù)組中用于配置程序可以自行補全哪些文件后綴
alias: {
'@': resolve('src'),
// 'vue$': 'vue/dist/vue.esm.js'
},
},
//提取公共代碼
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/, //表示默認拆分node_modules中的模塊
name: "vendor", //提取出來的文件命名
chunks: "all", //提取所有文件的公共部分
minChunks: 2, //表示提取公共部分最少的文件數(shù) 模塊被引用>=2次,拆分至vendors公共模塊
minSize: 0, //表示提取公共部分最小的大小 模塊超過0k自動被抽離成公共模塊
},
}
}
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader'],
exclude: /node_modules/,
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
"presets": ["@babel/env"],
"plugins":
["@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime"],
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /\.(eot?.+|svg?.+|ttf?.+|otf?.+|woff?.+|woff2?.+)$/,
use: 'file-loader?name=' + (isEnvProduction ? assetsPath('fonts/[name].[hash:8].[ext]') : 'fonts/[name].[hash:8].[ext]')
},
{
test: /\.(jpg|jpeg|png|gif|ico|svg)$/,
loader: 'url-loader',
options: {
limit: 10000,
name: isEnvProduction ? assetsPath('images/[name].[hash:8].[ext]') : 'images/[name].[hash:8].[ext]',
}
},
],
},
plugins: [
new ProgressBarPlugin(),
new VueLoaderPlugin(),
//ProvidePlugin是webpack的內(nèi)置模塊,使用ProvidePlugin加載的模塊在使用時將不再需要import和require進行引入
new Webpack.ProvidePlugin({
_: 'lodash',
}),
new HtmlWebpackPlugin({
template: './src/index.html', //文件路徑及名稱
filename: 'index.html', //輸出后的文件名稱
}),
new MiniCssExtractPlugin({
filename: isEnvProduction ? assetsPath("css/[name]-[hash].css") : "css/[name]-[hash].css",
chunkFilename: isEnvProduction ? assetsPath("css/[name]-[hash].css") : "css/[name]-[hash].css", //默認就是取的以id或name為開頭的css,所以可以加這行配置代碼,也可以不加
}),
],
devServer: {
port,
host: '0.0.0.0',
open: `http://localhost:${port}`,
stats: {
hash: false,
builtAt: false,
version: false,
modules: false,
children: false, ////解決類似Entrypoint undefined = index.html和Entrypoint mini-css-extract-plugin = *的警告
entrypoints: false,
colors: {
green: '\u001b[32m',
yellow: '\u001b[32m',
}
},
proxy: {
'/': {
target: '',
changeOrigin: true
}
},
inline: true,
compress: false,
disableHostCheck: true,
historyApiFallback: true,
},
}
關(guān)于配置中用到的一些插件的api就不一一展開詳解了,唯一需要說明的一點是,配置中所用到的插件的版本基本都是最新的,而使用postcss-loader時,需要在項目的根目錄新建一個postcss.config.js文件:
module.exports = {
plugins: {
'autoprefixer': {browsers: 'last 5 version'}
}
}
以上是開發(fā)環(huán)境的webpack配置,下邊是打包生產(chǎn)環(huán)境的配置webpack.product.config.js:
const path = require('path');
const config = require('./webpack.config');
const merge = require('webpack-merge');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //壓縮單獨的css文件
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin'); //資源清單
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); //監(jiān)控打包文件所花費的時間,方便具體的性能優(yōu)化
const smp = new SpeedMeasurePlugin();
const PurifyCSSPlugin = require("purifycss-webpack"); //css tree-shaking 依賴插件glob-all和purify-css
const glob = require("glob-all");
module.exports = smp.wrap(merge(config, {
mode: 'production',
stats: config.devServer.stats,
devtool: false,
//當(dāng)我們想在項目中require一些其他的類庫或者API,而又不想讓這些類庫的源碼被構(gòu)建到運行時文件中,這在實際開發(fā)中很有必要。此時我們就可以通過配置externals參數(shù)來解決這個問題
externals: {
'vue': 'Vue',
'vuex': 'Vuex',
'moment': 'moment',
'vue-router': 'VueRouter',
'element-ui': 'ELEMENT',
'ant-design-vue': 'antd', //使用externals html里需手動引入一下js,特別注意:還需額外引入moment.js,并放在antd之前,否則會報錯
'lodash': '_',
},
optimization: {
minimizer: [
new UglifyJsPlugin({
parallel: true, //使用多線程并行運行來提高構(gòu)建速度,默認并發(fā)運行數(shù)量:os.cpus().length - 1
uglifyOptions: {
compress: {
inline: false,
drop_console: true, //是否屏蔽掉控制臺輸出
},
}
}),
new OptimizeCSSAssetsPlugin() //壓縮css
]
},
plugins: [
new ManifestPlugin(),
new CleanWebpackPlugin(),
new PurifyCSSPlugin({
paths: glob.sync([
// 要做CSS Tree Shaking的路徑文件
path.resolve(__dirname, "../src/*.vue")
])
}),
new HtmlWebpackPlugin({
template: './src/index.prod.html', //打包時需要的文件路徑和名稱
filename: 'index.html', //打包輸出后的文件名稱
minify: { //壓縮html
removeComments: true, //刪除注釋
collapseWhitespace: true //刪除空格
}
}),
],
}));
打包的配置中有幾點需要注意:
1、配置中有一個speed-measure-webpack-plugin的插件,可以監(jiān)控打包文件所花費的時間,方便具體的性能優(yōu)化;
2、配置中加入了webpack-manifest-plugin生成資源清單的插件,這個插件所生成的資源清單對服務(wù)端渲染SSR非常有用,服務(wù)端可以根據(jù)當(dāng)前的manifest,引入css和js文件;
3、配置中引入了purifycss-webpack和glob-all兩個插件并依賴一個purify-css插件用來對css的tree-shaking。shake有搖動、抖動之意,言外之意就是通過抖動將項目中沒有使用卻定義了的js方法給刪除,降低打包后項目的體積,很形象哈。自webpack2開始,webpack就自帶了js的tree-shaking,卻沒有css的tree-shaking,所以我們就借助了插件來實現(xiàn)tree-shaking。
4、為了提高打包的速度以及降低打包后的項目體積,我們可以將項目中用到框架采用CDN的方式引入,從而將這部分框架排除在打包之外,而new HtmlWebpackPlugin配置項中的template的路徑引用的index.prod.html文件就是采用CDN的方式引入的第三方的框架,區(qū)分了開發(fā)環(huán)境中的index.html。提升構(gòu)建速度也可以通過DllPlugin和DLLReferencePlugin插件來實現(xiàn),具體配置可參考:http://chabaoo.cn/article/162789.htm
vue的項目目錄:

react項目的webpack配置跟vue項目的webpack配置大同小異,這里不再多說,最后奉上package.json:
{
"name": "webpackvue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "cross-env BABEL_ENV=development webpack-dev-server --config config/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config config/webpack.product.config.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.4.4",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@babel/runtime": "^7.4.4",
"autoprefixer": "^9.5.1",
"babel-loader": "^8.0.6",
"babel-plugin-import": "^1.11.2",
"clean-webpack-plugin": "^2.0.2",
"cross-env": "^5.2.0",
"css-loader": "^2.1.1",
"file-loader": "^3.0.1",
"glob-all": "^3.1.0",
"html-webpack-plugin": "^3.2.0",
"lodash": "^4.17.11",
"mini-css-extract-plugin": "^0.6.0",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"postcss-loader": "^3.0.0",
"progress-bar-webpack-plugin": "^1.12.1",
"purify-css": "^1.2.5",
"purifycss-webpack": "^0.7.0",
"sass-loader": "^7.1.0",
"speed-measure-webpack-plugin": "^1.3.1",
"style-loader": "^0.23.1",
"uglifyjs-webpack-plugin": "^2.1.3",
"url-loader": "^1.1.2",
"vue-loader": "^15.7.0",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.31.0",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.3.1",
"webpack-manifest-plugin": "^2.0.4",
"webpack-merge": "^4.2.1"
},
"dependencies": {
"ant-design-vue": "^1.3.9",
"element-ui": "^2.8.2",
"moment": "^2.24.0",
"vue": "^2.6.10",
"vue-router": "^3.0.6",
"vuex": "^3.1.1"
}
}
總結(jié)
以上所述是小編給大家介紹的使用webpack搭建vue項目及注意事項,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!
相關(guān)文章
vscode搭建vue環(huán)境完整圖文教程(適合新手小白)
Vue框架的優(yōu)秀設(shè)計和強大的生態(tài)系統(tǒng)成為了越來越多開發(fā)者選擇Vue的原因,在實際項目過程中一個高效的開發(fā)環(huán)境能夠大大提高開發(fā)效率,這篇文章主要給大家介紹了關(guān)于vscode搭建vue環(huán)境的相關(guān)資料,需要的朋友可以參考下2023-10-10
vue中計算屬性(computed)、methods和watched之間的區(qū)別
這篇文章主要給大家介紹了關(guān)于vue中計算屬性(computed)、methods和watched之間區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-07-07

