一、node知識
__dirname: 擷取目前檔案所在路徑,等同于path.dirname(__filename)
console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
path.resolve([..paths]) : 把一個路徑或路徑片段的序列解析為一個絕對路徑
- 給定的路徑的序列是從右往左被處理的,後面每個 path 被依次解析,直到構造完成一個絕對路徑
- 如果處理完全部給定的 path 片段後還未生成一個絕對路徑,則目前工作目錄會被用上
- 生成的路徑是規範化後的,且末尾的斜杠會被删除,除非路徑被解析為根目錄
- 長度為零的 path 片段會被忽略
- 如果沒有傳入 path 片段,則 path.resolve() 會傳回目前工作目錄的絕對路徑
path.resolve('/foo/bar', './baz');
// 傳回: '/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/');
// 傳回: '/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果目前工作目錄為 /home/myself/node,
// 則傳回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
二、配置最基本的webpack
項目目錄生成如下檔案
.
├── build
│ ├── build.js
│ ├── index.html
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── package.json
├── package-lock.json
└── src
├── App.vue
├── main.js
├── timg.gif
└── timg.jfif
首先,先裝下webpack依賴:
npm i webpack webpack webpack-cli -D
1、webpack.base.conf.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
bundle: path.resolve(__dirname, '../src/main.js')
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].[hash].js',
publicPath: '/'
},
module: {
rules: [
]
},
plugins: [
<!-- 以目前目錄的index.html為模闆生成新的index.html,這個插件就是将新生成的檔案(js,css)引入 -->
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'index.html')
})
],
resolve: {
}
};
上面用到了html-webpack-plugin插件,裝下:
npm i html-webpack-plugin -D
2、webpack.dev.conf.js
const merge = require('webpack-merge');
const path = require('path');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
// mode關系到代碼壓縮品質 https://webpack.docschina.org/guides/tree-shaking/
mode: 'development',
// source-map,将編譯後的代碼映射到原代碼,便于報錯後定位錯誤
devtool: 'inline-source-map',
<!-- webpack-dev-server配置項 -->
devServer: {
<!-- devserver啟動服務的根路徑 -->
contentBase: path.resolve(__dirname, '../dist'),
<!-- 打開浏覽器 -->
open: true
}
});
合并webpack配置的插件webpack-merge,能夠啟一個簡易服務的webpack-dev-server,
詳情npm i webpack-dev-server webpack-merge -D
3、webpack.prod.conf.js
const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
mode: 'production',
devtool: 'source-map',
module: {
rules: []
},
plugins: [
new CleanWebpackPlugin(['dist/'], {
root: path.resolve(__dirname, '../')
})
]
});
清除檔案的插件:
npm i clean-webpack-plugin -D
4、build.js
const webpack = require('webpack');
const config = require('./webpack.prod.conf');
webpack(config, (err, stats) => {
if (err || stats.hasErrors()) {
// 在這裡處理錯誤
console.error(err);
return;
}
// 處理完成
console.log(stats.toString({
chunks: false, // 使建構過程更靜默無輸出
colors: true // 在控制台展示顔色
}));
});
5、 npm scripts
// package.json
{
+++
"scripts": {
"build": "node build/build.js",
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js"
},
}
以上算是一個webpack的基本結構,如果入口檔案(main.js)裡引入的是正經js,npm dev和npm build是可以的打包編譯的,但是我們是要寫vue,那就要加些loader和plugins了
三、引入一些基本的loader
1、babel-loader
依賴安裝要求:webpack 4.x | babel-loader 7.x | babel 6.x,注意babel-loader和babel的版本,不然會報錯
npm install -D babel-loader@7 babel-core babel-preset-env webpack
然後再配置中加入
// base.conf.js
module.exports = {
+++
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
+++
]
}
}
我們還需要添加一個配置檔案(.babelrc)在根目錄下:
/// .babelrc
{
"presets": [
["env", {
"targets": {
"browsers": [">0.25%", "last 2 versions", "not ie 11", "not op_mini all"]
}
}]
]
}
這就是 babel-preset-env 的作用,幫助我們配置 babel。我們隻需要告訴它我們要相容的情況(目标運作環境),它就會自動把代碼轉換為相容對應環境的代碼。
以上代碼表示我們要求代碼相容最新兩個版本的浏覽器,不用相容 11(及以下)和Opera Mini,另外市場佔有率超過 0.25% 的浏覽器也必須支援。
隻需要告訴 babel-preset-env 你想要相容的環境,它就會自動轉換
2、url-loader、file-loader
如果我們希望在頁面引入圖檔(包括img的src和background的url)。當我們基于webpack進行開發時,引入圖檔會遇到一些問題
其中一個就是引用路徑的問題。拿background樣式用url引入背景圖來說,我們都知道,webpack最終會将各個子產品打包成一個檔案,是以我們樣式中的url路徑是相對入口html頁面的,而不是相對于原始css檔案所在的路徑的。這就會導緻圖檔引入失敗。這個問題是用file-loader解決的,file-loader可以解析項目中的url引入(不僅限于css),根據我們的配置,将圖檔拷貝到相應的路徑,再根據我們的配置,修改打包後檔案引用路徑,使之指向正确的檔案
另外,如果圖檔較多,會發很多http請求,會降低頁面性能。這個問題可以通過url-loader解決。url-loader會将引入的圖檔編碼,生成dataURl。相當于把圖檔資料翻譯成一串字元。再把這串字元打包到檔案中,最終隻需要引入這個檔案就能通路圖檔了。當然,如果圖檔較大,編碼會消耗性能。是以url-loader提供了一個limit參數,小于limit位元組的檔案會被轉為DataURl,大于limit的還會使用file-loader進行copy。
url-loader和file-loader是什麼關系呢?簡答地說,url-loader封裝了file-loader。url-loader賴于file-loader,即使用url-loader時,也要安裝file-loader
npm i url-loader file-loader -D
/// base.conf.js
module.exports = {
+++
module: {
rules: [
+++
{
test: /\.(png|jpg|jfif|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 低于這個limit就直接轉成base64插入到style裡,不然以name的方式命名存放
// 這裡的機關時bit
limit: 8192,
name: 'static/images/[hash:8].[name].[ext]'
}
}
]
},
// 字型圖示啥的,跟圖檔分處理方式一樣
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'url-loader',
name: 'static/font/[hash:8].[name].[ext]'
}
]
},
]
},
}
3、 vue-loader
作用自己去看
npm i vue-loader -D
// base.conf.js
module.exports = {
+++
module: {
rules: [
+++
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
}
}
在這裡還要一個插件,這個插件是必須的!
// base.conf.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
+++
plugins: [
// 它的職責是将你定義過的其它規則複制并應用到 .vue 檔案裡相應語言的塊。
// 例如,如果你有一條比對 /\.js$/ 的規則,那麼它會應用到 .vue 檔案裡的 <script> 塊
new VueLoaderPlugin(),
+++
]
}
4、處理樣式
- less-loader: 将less轉css
- css-loader: 将css轉為CommonJS規範的js字元串
- style-loader: 将js字元串轉為style node插入到html中
- postcss-loader: PostCSS 是一個允許使用 JS 插件轉換樣式的工具,我們用postcss的插件就要配置它,autoprefixer就是postcss項目裡的一個插件
- autoprefixer: 添加了 vendor 浏覽器字首,它使用 Can I Use 上面的資料。
npm i less-loader css-loader style-loader less autoprefixer postcss-loader -D
const StyleLintPlugin = require('stylelint-webpack-plugin');
// base.conf.js
module.exports = {
+++
module: {
rules: [
{
// less css
test: /\.l?css$/,
// use裡的loader執行順序為從下到上,loader的順序要注意
// 這裡檢測到less/css檔案後需要将後續處理loader都寫在此use裡,如果less和css過分開檢測處理,不能說先用less-loader轉成css,然後讓它走/\.css/裡的use
use: [
{loader: 'style-loader'},
{loader: 'css-loader'},
{loader: 'postcss-loader'},
{loader: 'less-loader'},
]
},
+++
]
}
}
- 配置postcss
在根目錄建立個postcss.config.js檔案來配置autoprefixer,通過 Browerslist 來幫助你配置,浏覽器市場佔有率,了解下 browserl.ist
module.exports = {
plugins: [
require('autoprefixer')({
"browsers": [
"defaults",
"not ie < 9",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
})
]
}
- mini-css-extract-plugin提取css
這裡打包以
css
為例,r如果要用
less
插件提取
mini-css-extract-plugin
,将上面改為如下:
css
npm install mini-css-extract-plugin -D
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+++
module.exports = {
+++
// 子產品,loader
module: {
rules: [
+++
{
test: /\.l?(c|e)ss$/,
use: [
MiniCssExtractPlugin.loader,
{loader: 'css-loader'},
{loader: 'postcss-loader'},
{loader: 'less-loader'},
]
},
+++
]
},
// 插件
plugins: [
+++
new MiniCssExtractPlugin({
filename: 'static/css/[name].[hash].css',
chunkFilename: 'static/css/[name].[hash].css'
})
]
}
5、然後配置下别名resolve.extensions
// base.conf.js
module.exports = {
+++
resolve: {
alias: {
// 配置别名'vue$',不然import 'vue'時,webpack找不到
'vue$': 'vue/dist/vue.esm.js',
// 這個為src配置别名,非必需,為友善而已
'@': path.resolve(__dirname, '../src')
},
// 在import這些拓展名的檔案時,可以省略拓展名
extensions: ['*', '.js', '.json', '.vue'],
}
}
現在我們來測試以下,安裝一個vue
npm i vue
在mian.js裡面
import Vue from 'vue'
import App from './App'
new Vue({
el: '#app',
components: {App},
template: '<App/>'
})
在App.vue裡寫入
<template>
<div>
<h3 class="title">{{title}}</h3>
<p class="content">{{content}}</p>
<div class="goddess">
<div class="right">
<h4 class="right__h4">background引入圖檔</h4>
<div class="right__img"></div>
</div>
<div class="left">
<h4 class="left__h4">img标簽直接引入圖檔</h4>
<img class="left__img" src="./timg.jfif" />
</div>
</div>
</div>
</template>
<script>
export default {
components: {
Foot: Footer
},
data () {
return {
title: 'hello word',
content: 'webpack4 搭建vue環境',
}
},
}
</script>
<style lang="less" scoped>
.title {
font-size: 20px;
text-align: center;
color: red;
}
.content {
font-size: 14px;
color: #333333;
}
.goddess {
.left {
margin-left: 50%;
&__h4 {
font-size: 14px;
}
&__img {
width: 308px;
height: 433px;
}
}
.right {
float: left;
&__h4 {
font-size: 14px;
}
&__img {
width: 300px;
height: 150px;
background: url('./timg.gif') no-repeat;
}
}
}
</style>
好了,npm dev 先看一下女神,放松一下:

四、做一些優化
1、提取公共代碼
使用 splitChucksPlugin 插件,這是 Webpack 自帶的,不用安裝第三方依賴,預設配置即可
<!-- base.conf.js -->
module.exports = {
+++
plugins: [
+++
new webpack.optimize.SplitChunksPlugin()
]
}
想了解這個插件的預設配置及如何配置,
英文,
中文2、将第三方庫單獨打包
每次我們對項目進行打包時,我們都會把引用的第三方依賴給打包一遍,比如 Vue、Vue-Router、React 等等。但是這些庫的代碼基本都是不會變動的,我們沒必要每次打包都建構一次,是以我們最好将這些第三方庫提取出來單獨打包,這樣有利于減少打包時間。
官方插件是
DllPlugin。推薦一個比較好用的插件 —— autodll-webpack-plugin
npm i autodll-webpack-plugin -D
// base.conf.js
module.exports = {
+++
plugins: [
// 将一些不太可能改動的第三方庫單獨打包,會通過緩存極大提升打包速度
new AutoDllPlugin({
// will inject the DLL bundle to index.html
// default false
inject: true,
debug: false,
filename: '[name]_[hash].js',
path: 'static',
entry: {
// [name] = vue, 在這裡會将entry裡的每個item(vue,jquery)都打包成一個js
vue: [
'vue',
'vue-router'
],
// [name] = jquery
// jquery: [
// 'jquery',
// 'jquery-from'
// ]
}
}),
+++
]
}
inject 為 true,插件會自動把打包出來的第三方庫檔案插入到 HTML。filename 是打包後檔案的名稱。path 是打包後的路徑。entry 是入口,vendor 是你指定的名稱,數組内容就是要打包的第三方庫的名稱,不要寫全路徑,Webpack 會自動去 node_modules 中找到的。
每次打包,這個插件都會檢查注冊在 entry 中的第三方庫是否發生了變化,如果沒有變化,插件就會使用緩存中的打封包件,減少了打包的時間,這時 Hash 也不會變化。
3、熱重載
“熱重載”不隻是當你修改檔案的時候簡單重新加載頁面。啟用熱重載後,當你修改 .vue 檔案時,該元件的所有執行個體将在不重新整理頁面的情況下被替換。它甚至保持了應用程式和被替換元件的目前狀态!當你調整模版或者修改樣式時,這極大地提高了開發體驗,以下兩種方式擇一即可
- 方式1:啟動的時候通過
選項就ok了, webpack--hot
"scripts": {
+++
"dev": "webpack-dev-server --hot --inline --progress --config build/webpack.dev.conf.js"
},
- 方式2:或者通過配置webpack.dev.config.js,相比第一種,就會麻煩一點
const webpack = require('webpack')
module.exports = {
+++
module: {
devServer: {
+++
// 開啟熱重載
hot: true
},
plugins: [
// 啟用子產品熱替換(HMR)
new webpack.HotModuleReplacementPlugin(),
// 當開啟 HMR 的時候使用該插件會顯示子產品的相對路徑,建議用于開發環境。
new webpack.NamedModulesPlugin(),
+++
]
}
}
4、eslint
確定
VS Code
安裝了
Vetur(設定編輯器支援vue檔案,如果寫過vue忽略)
和
Eslint
插件
npm i -g eslint@latest
eslint --init
然後選個最流行的就行了
會幫你建立一個.eslintrc.js 的配置檔案以及裝一些 eslint 的依賴
在 package.json 裡加上:
{
+++
"scripts": {
+++
"lint": "eslint --ext .js,.vue src"
},
}
你可以嘗試的
npm run lint
,你會發現
spacing 系列
、
no-new
.vue文法不支援
等問題
當然,你可以通過改寫 lint 指令(加個
--fix
)來解決部分文法報錯
{
+++
"scripts": {
+++
"lint": "eslint --fix --ext .js,.vue src"
},
}
或者儲存的時候讓 eslint 插件自動修複。 更改 VS Code 中的 eslint.autoFixOnSave 設定,勾選文本編輯->Format On Save
當然這玩法不是我們這裡的重點,安裝 eslint-plugin-html 來解決vue文法eslint報錯問題
npm install -D eslint-plugin-html
在.eslintrc.js 中配置 eslint-plugin-html
module.exports = {
+++
"plugins": [
// 使用eslint-plugin-html
"html"
]
};
至于 main.js 裡的 new 指定給變量錯誤 disable 掉
+++
/* eslint-disable no-new */
new Vue({
el: '#app',
components: {
App
},
template: '<App/>'
})
- 代碼如果eslint有報錯,就讓編譯不通過
npm i eslint-loader babel-eslint -D
<!-- .eslintrc.js -->
{
+++
"parser": "babel-eslint"
}
<!-- base.config.js -->
module.exports = {
module: {
rules: [
{
test: /\.(vue|js)$/,
loader: 'eslint-loader',
exclude: /node_modules/,
// 預處理
enforce: 'pre',
include: [path.join(__dirname, '..', 'src')]
}
]
}
}
- 代碼送出之前對代碼進行檢查
npm i husky -D
<!-- package.json -->
{
+++
"script": {
+++
"precommit": "eslint --fix --ext .js --ext .vue src/"
}
}
該工具可以在我們送出代碼時,調用"precommit"鈎子,執行預處理操作,eslint不通過,無法送出
在送出時僅對
git add
的 js,vue 檔案進行檢測
lint-staged 和 husky 在 pre-commit 階段做代碼檢查npm i lint-staged -D
<!-- package.json -->
{
+++
"script": {
+++
"precommit": "lint-staged"
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
}
5、引入jquery shimming
npm i juery -D
<!-- base.config.js -->
module.exports = {
+++
plugins: [
+++
new webpack.ProvidePlugin({
$: 'jquery'
})
]
};
這樣就可以将$當全局變量使用了,當然eslint要配置個global,這裡不介紹了
對你有幫助的話點個刷波6,點個贊吧
原文位址:
https://segmentfault.com/a/1190000016972438