前言
在前面的篇章中,已經說明了 webpack4 的基本使用,那麼本章節開始在 webpack4 中構建vue項目,同時對比看看這種構建方式,與在網頁script導入 vue.js 中的區別。
構建webpack項目開發
首先重新構建webpack項目。
初始化項目文件結構
初始化 package.json 文件
package.json 使用存儲記錄 npm 安裝相關包版本即可的。執行以下命令進行初始化:
npm init -y
執行如下:
安裝webpack
安裝webpack工具至本地項目中:
npm i -D webpack webpack-cli
在項目根目錄創建、編寫配置文件 webpack.config.js
const path = require('path');
// 這個配置文件,起始就是一個 JS 文件,通過 Node 中的模塊操作,向外暴露了一個 配置對象
module.exports = {
// 在配置文件中,需要手動指定 入口 和 出口
entry: path.join(__dirname, './src/main.js'),// 入口,表示,要使用 webpack 打包哪個文件
output: { // 輸出文件相關的配置
path: path.join(__dirname, './dist'), // 指定 打包好的文件,輸出到哪個目錄中去
filename: 'bundle.js' // 這是指定 輸出的文件的名稱
},
};
一般來說,現在就可以執行 webpack 命令進行打包了,但是我在上面將 webpack 安裝到本地項目中,所以還需要編寫 npm 執行內部命令的腳本,才能夠執行。
在 package.json 配置執行本地 webpack 執行命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
好了,配置了這個之後,就可以使用 npm run 腳本名稱
來執行了,執行如下:
npm run build
可以看到已經可以成功編輯打包出 bundle.js
壓縮文件了。
編寫main.js
打印信息,設置 index.html 引用 bundle.js 腳本
首先在main.js
寫一個打印信息,如下:
console.log("hello world");
然後在index.html
引入bundle.js
,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="../dist/bundle.js"></script>
</body>
</html>
安裝babel
安裝babel至本地項目中:
npm i -D babel-loader @babel/core
爲了轉化 es6 代碼,要安裝 babel 插件:
npm i -D @babel/preset-env @babel/polyfill
安裝防止全局污染babel插件
npm i -D @babel/plugin-transform-runtime
npm i -S @babel/runtime @babel/runtime-corejs2
注意:使用 -D
也就是 --save-dev
,將其安裝好測試開發環境, 而 -S
也就是 --save
,將其安裝到生產環境的依賴中。
在根目錄下創建 babel 配置文件 .babelrc:
{
"presets": ["@babel/preset-env"],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}
注意:"corejs": 2, // 這裏設置2是因爲上面安裝的版本是 @babel/runtime-corejs2
配置webpack.config.js設置使用babel的規則
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
]
}
在main.js中寫入ES6語法,查看打印信息
在安裝babe將ES6\ES7轉化低於語法ES5之前,我先經過測試,發現使用ES6的語法在chrome瀏覽器是能夠支持運行的,而在IE則會報語法錯誤,如下:
main.js 代碼如下:
// ES5
console.log("hello world es5");
// ES6
class Bar {
doStuff() {
console.log('stuff bar');
}
}
var b = new Bar();
b.doStuff(); // "stuff"
// ES6
class Foo {
static classMethod() {
return 'hello static foo';
}
}
console.log(Foo.classMethod()); // 'hello'
執行npm run build
打包編譯一下,看看 ie瀏覽器能否識別打印高級語法的信息,如下:
安裝webpack-dev-server
安裝webpack-dev-server至本地項目:
npm i webpack-dev-server -D
運行webpack-dev-server命令
在package.json
的scripts
編寫執行命令,如下:
"scripts": {
"dev": "webpack-dev-server"
},
啓動了server服務之後,輸入文件的路徑修改爲 / 根路徑
啓動執行服務如下:
npm run dev
修改 index.html
引入 bundle.js
的路徑,並且刪除dist目錄下的bundle.js
文件
webpack-dev-server的常用命令參數
"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"
-- open
: 設置啓動服務自動打開瀏覽器
--port 端口號
:配置服務啓動端口號
--contentBase src
: 啓動服務設置index.html
的所在目錄
--hot
:設置採用補丁的方式熱更新
使用html-webpack-plugin
插件配置啓動頁面
前面在配置生成bundle.js
的使用時候,已經將其存儲在內存中編譯生成。那麼能不能將index.html
頁面也加載存儲到內存中呢?
這個當然可以,可以使用html-wabpack-plugin
插件來完成這部分工作。
安裝html-wabpack-plugin
插件
npm i html-webpack-plugin -D
在webpack.config.js
配置文件中配置
const path = require('path');
// 導入在內存中生成 HTML 頁面的 插件
// 只要是插件,都一定要 放到 plugins 節點中去
// 這個插件的兩個作用:
// 1\. 自動在內存中根據指定頁面生成一個內存的頁面
// 2\. 自動,把打包好的 bundle.js 追加到頁面中去
const htmlWebpackPlugin = require('html-webpack-plugin');
// 這個配置文件,起始就是一個 JS 文件,通過 Node 中的模塊操作,向外暴露了一個 配置對象
module.exports = {
// 在配置文件中,需要手動指定 入口 和 出口
entry: path.join(__dirname, './src/main.js'),// 入口,表示,要使用 webpack 打包哪個文件
output: { // 輸出文件相關的配置
path: path.join(__dirname, './dist'), // 指定 打包好的文件,輸出到哪個目錄中去
filename: 'bundle.js' // 這是指定 輸出的文件的名稱
},
devServer: { // 這是配置 dev-server 命令參數的第二種形式,相對來說,這種方式麻煩一些 // --open --port 3000 --contentBase src --hot
open: true, // 自動打開瀏覽器
port: 3000, // 設置啓動時候的運行端口
contentBase: 'src', // 指定託管的根目錄
hot: true // 啓用熱更新
},
plugins: [ // 配置插件的節點
new htmlWebpackPlugin({ // 創建一個 在內存中 生成 HTML 頁面的插件
template: path.join(__dirname, './src/index.html'), // 指定 模板頁面,將來會根據指定的頁面路徑,去生成內存中的 頁面
filename: 'index.html' // 指定生成的頁面的名稱
})
],
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
]
}
};
啓動服務,發現bundle.js被自動引入
這個插件的兩個作用:
- 自動在內存中根據指定頁面生成一個內存的頁面
- 自動,把打包好的 bundle.js 追加到頁面中去
使用webpack打包css文件
安裝style-loader css-loader
工具,用於處理css
文件
npm i style-loader css-loader -D
在webpack.config.js
這個配置文件設置匹配css
文件處理的插件
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }, // 配置處理 .css 文件的第三方loader 規則
使用webpack打包less文件
安裝less-loader less工具來處理less文件
npm i less-loader less -D
在webpack.config.js
配置文件設置匹配less文件的處理
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, //配置處理 .less 文件的第三方 loader 規則
使用webpack打包sass文件
安裝sass-loader node-sass工具來處理sass文件
cnpm i sass-loader node-sass -D
cnpm i sass fiber -D
在webpack.config.js
配置文件設置匹配scss文件的處理
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, // 配置處理 .scss 文件的 第三方 loader 規則
webpack 中 url-loader 的使用
安裝url-loader
cnpm i url-loader file-loader -D
在webpack.config.js
中添加處理url路徑的loader模塊:
{ test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=500&name=[hash:8]-[name].[ext]' },
上面這種輸入參數的方式還有另一種方式,以對象的鍵值對方式,如下:
{
test: /\.(jpg|png|gif|bmp|jpeg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 500, //是把小於500B的文件打成Base64的格式,寫入JS
name: '[hash:8]-[name].[ext]' // [hash:8] 在名稱前面設置8位哈希值,[name] 設置文件的原名, [ext] 設置文件的原後綴
}
}]
},// 處理 圖片路徑的 loader
區分webpack中導入vue和普通網頁使用script導入Vue的區別
上面已經構建好了webpack的基本使用組件,那麼下面可以開始在webpack中開始探討使用vue的方法。
那麼首先來回顧一下普通網頁使用script導入vue的過程,如下:
- 使用 script 標籤 ,引入 vue 的包
- 在 index 頁面中,創建 一個 id 爲 app div 容器
- 通過 new Vue 得到一個 vm 的實例
通過這三個步驟,我們就可以開始 vue 開發了。但是在webpack中也是這樣麼?
安裝vue庫
首先在項目本地安裝 vue 庫先,如下:
cnpm i vue -S
將vue安裝到生產依賴中,執行如下:
在webpack嘗試導入vue 以及 創建 vm
1. 上面安裝完畢vue庫之後,下面在main.js
嘗試導入 vue,如下:
// 導入vue
import Vue from 'vue'
2.創建vm實例
// 創建vm
var vm = new Vue({
el: '#app',
data: {}
});
3.在index.html創建app容器
4.在vm的data中設置一個msg值,然後在app中渲染看看
main.js 如下:
index.html 渲染數據如下:
啓動服務查看是否正常渲染效果,如下:
vue.runtime.esm.js:620 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
這裏提示使用 vue.runtime.esm.js
只會構建運行時的 vue 代碼,無法使用模板編譯。提示可以使用 render
方法返回組件,或者使用內置的編譯器構建。
5.問題的根本原因:
在 webpack 中, 使用 import Vue from 'vue' 導入的 Vue 構造函數,功能不完整,只提供了 runtime-only 的方式,並沒有提供 像網頁中那樣的使用方式;
那麼如果想要使用網頁script
直接導入的方式,這時候就需要導入完整的 Vue 功能的js。那麼這個完整的 Vue 功能 js 其實就是需要在 nodemodules 裏面去查找。
包的查找規則:
1.找項目根目錄中有沒有 node_modules 的文件夾
2.在 node_modules 中 根據包名,找對應的 vue 文件夾
3.在 vue 文件夾中,找 一個叫做 package.json 的包配置文件
4.在 package.json 文件中,查找一個 main 屬性【main屬性指定了這個包在被加載時候的入口文件】
這說明當 import
這個庫的時候,則會導入 main
屬性指定的文件。
如果需要想要完整的功能,應該是要導入完整的 vue.js ,如下:
6.修改導入vue庫的方式,使其支持完整功能
如果想要修改導入vue的 js,有兩種方式,
第一種就是直接在 vue 庫的package.json中main中修改引入的文件,
第二種則是 import 的時候直接手寫引入的文件路徑。
先來看看第一種,如下:
將原來引入的代碼
"main": "dist/vue.runtime.common.js",
"module": "dist/vue.runtime.esm.js",
改爲
"main": "dist/vue.min.js",
"module": "dist/vue.min.js",
此時,再來編譯服務,可以看到瀏覽器正常渲染數據了。
但是一般來說,我們不會修改庫的文件方式。下面來看看第二種,再次之前將庫文件的main屬性改回去。
第二種方式:
此時查看編譯後能否查看渲染數據,如下:
可以看到也可以正常如同網頁 script 引入一樣渲染數據了。
但是如果將導入vue寫成這樣路徑寫法:
import Vue from '../node_modules/vue/dist/vue.min.js'
看上去非常不優雅,能否依然是寫成
import Vue from 'vue'
但是又不修改vue庫的main屬性,又可以導入實際vue.min.js
完整功能的腳本呢?
此時就要使用resolve
屬性來設置導入庫別名 alias
了。
7.在webpack.config.js
中添加resolve
屬性:
首先將導入包的方式改回去,如下:
在webpack.config.js
添加resolve
屬性,如下:
resolve: {
alias: {
'vue$': 'vue/dist/vue.min.js'
}
}
再次編譯運行服務,確認是否模板渲染正常,可以發現也是可以正常渲染的。
總結區別
從上面的過程中可以發現webpack默認導入vue的話,導入的是run-time-only
的非完整js,而我們在普通網頁中使用的,一般導入完整的vue庫文件。
如果需要修改使用模板渲染的功能,那麼只能修改一下vue導入的文件了。
在vue中結合render函數渲染指定的組件到容器中
那麼是否存在我依然使用run-time-only
的vue庫,依然可以將組件渲染到 app容器的方式呢?
這個當然有,就是使用render
函數。
爲了演示效果,我們先將上面設置的alias
註釋,改回使用run-time-only
庫。
下面來創建一個login組件,然後將其渲染到容器中。
1.創建login組件
// 創建login組件
var login = {
template: "<h1>這是login組件。</h1>"
};
2.首先按照完整功能的方式註冊到vm中,然後在index.html中使用組件,查看能否正常
main.js 中註冊組件login
index.html 中使用組件login
啓動服務,查看能否正常顯示,如下:
3.將login組件寫到 login.vue
文件中,然後使用render函數來渲染組件
在上面的示例看到,使用run-time-only
的 vue
,無法使用模板直接在 vm
中渲染組件。那麼下面我們抽離 login
組件出來到 login.vue
文件中,然後使用 render
來返回渲染 login
組件。看看效果。
3.1 編寫 login.vue 文件
<template>
<div>
<h1>這是login登錄組件</h1>
</div>
</template>
<script>
</script>
<style>
</style>
可以看到 vue 文件主要分爲了三部分:template 、script、 style
那麼下面先來看看如果直接當作組件導入會是什麼效果。
3.2 導入login組件
那麼下面啓動服務,看看頁面,如下:
3.3 安裝編譯vue文件的插件
默認webpack是無法編譯vue文件的,需要安裝相關的插件。
安裝命令:
npm i vue-loader vue-template-compiler -D
npm i vue-loader-plugin -S
執行如下:
在webpack.config.js
中,添加如下module
規則:
{ test: /\.vue$/, use: 'vue-loader' }, // 配置處理 .vue 文件
還要配置插件:
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
// ...
plugins: [
new VueLoaderPlugin()
]
}
再次編譯,此時已經沒有報錯了,頁面只是提示runtime-only
的告警信息,如下:
3.4 使用render函數渲染組件
// 使用render函數渲染組件
render: function (createElements) {
return createElements(login)
}
此時網頁看看是否成功渲染組件,如下:
可以看到已經成功渲染組件了。
下面簡寫一下render函數,如下:
// 使用render函數渲染組件
render: c => c(login)
總結
總結梳理: webpack
中如何使用 vue
:
1.安裝vue的包:
cnpm i vue -S
2.由於 在 webpack 中,推薦使用 .vue 這個組件模板文件定義組件,所以,需要安裝 能解析這種文件的
npm i vue-loader vue-template-compiler -D
npm i vue-loader-plugin -S
- 3.在
main.js
中,導入vue
模塊import Vue from 'vue'
- 4.定義一個
.vue
結尾的組件,其中,組件有三部分組成:template
script
style
- 5.使用
import login from './login.vue'
導入這個組件 - 6.創建
vm
的實例var vm = new Vue({ el: '#app', render: c => c(login) })
- 7.在頁面中創建一個
id
爲app
的div
元素,作爲我們vm
實例要控制的區域;
更多精彩原創Devops文章,快來關注我的公衆號:【Devops社羣】 吧: