@TOC
本地環(huán)境
node -v // v9.1.0
npm -v // 6.5.0
webpack -v // 4.32.2
webpack-cli -v // 3.3.2
這里需要注意的是webpack4+以后需要單獨(dú)安裝webpack-cli
起步
1.初始化項(xiàng)目
npm init
一直enter生成package.json文件(小技巧:npm init -y 可以免去繁瑣的enter)
2.安裝依賴
npm i webpack webpack-cli webpack-dev-server --save-dev
想要深入上述依賴請(qǐng)轉(zhuǎn)webpack文檔
依賴安裝成功接下來(lái)就開(kāi)始動(dòng)手吧
3.目錄文件配置
根目錄鼠標(biāo)右鍵新建index.html webpack.config.js src文件夾或:
// window
type >webpcak.config.js
type >index.html
md src
//mac 土豪玩家
touch webpcak.config.js
touch index.html
mkdir src
src目錄下面新建 main.js
此時(shí)目錄如下
project/
src/
main.js
webpack.config.js
index.html
package.json
內(nèi)容如下:
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack從零搭設(shè)</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
modul.exports = {}
4.配置index.html及webpack.config.js
首先
main.js修改如下:
// src/main.js
console.log('hello world');
webpack.config.js修改如下:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = { // module.exports commonjs規(guī)范
entry: './src/main.js', // 項(xiàng)目入口文件暇赤,webpack將從main.js開(kāi)始,把所有依賴的js都打包
output: {
path: path.resolve(__dirname, './dist'), // 項(xiàng)目的打包后的輸出路徑 可修改
publicPath: '/dist/', // 通過(guò)devServer訪問(wèn)路徑 可修改
filename: 'build.js' // 打包后的文件名 可修改
},
devServer: {
historyApiFallback: true, // When using the HTML5 History API, the `index.html` page will likely have to be served in place of any `404` responses
overlay: true //Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors
},
};
webpack配置里的核心:
- entry: webpack打包的入口(不是代碼執(zhí)行入口)重抖;
- output: webpack打包后生成的靜態(tài)資源文件棒妨,最終會(huì)被html引用踪古;
- loader: 轉(zhuǎn)化非js文件成webpack能夠處理的js文件;對(duì)js文件進(jìn)行加工券腔;
- plugins: 顧名思義---webpack打包過(guò)程中輔助插件伏穆;
index.html 修改如下 增加引入打包后的js
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack從零搭設(shè)</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="/dist/build.js"></script>
</html>
package.json修改如下:
"scripts": {
"dev": "webpack-dev-server --open --hot",
"build": "webpack --progress --hide-modules"
},
webpack-dev-server會(huì)啟動(dòng)一個(gè)靜態(tài)資源web服務(wù)器 --hot參數(shù)表示啟動(dòng)熱更新
重新啟動(dòng)服務(wù)
npm run dev
打開(kāi)控制臺(tái)可以看到 有輸出hello world
5.vue的起步
安裝vue
npm install vue --save
修改main.js如下
// src/main.js
import Vue from 'vue';
// import Vue from 'vue/dist/vue.esm.js' // 解決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
// console.log('hello world');
var app = new Vue({
el: '#app',
data: {
mess: 'Hello Vue@2.0!'
}
})
此時(shí) 修改index.html如下:
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack從零搭設(shè)</title>
</head>
<body>
<div id="app">
{{ mess }}
</div>
</body>
<script src="/dist/build.js"></script>
</html>
重新啟動(dòng)服務(wù)
npm run build
npm run dev
此時(shí)
查閱資料發(fā)現(xiàn):
vue有兩種形式的代碼 compiler(模板)模式和runtime模式(運(yùn)行)
vue模塊的package.json的main字段默認(rèn)為runtime模式枕扫, 指向"dist/vue.runtime.common.js"位置。這是vue升級(jí)到2.0之后就有的特點(diǎn)涛酗。
但此時(shí)我們main.js的寫法是
// src/main.js
import Vue from 'vue';
// import Vue from 'vue/dist/vue.esm.js' // 解決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
// console.log('hello world');
var app = new Vue({
el: '#app',
data: {
mess: 'Hello Vue@2.0!'
}
})
解決方案 一
// src/main.js
//import Vue from 'vue';
import Vue from 'vue/dist/vue.esm.js' // 解決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
// console.log('hello world');
var app = new Vue({
el: '#app',
data: {
mess: 'Hello Vue@2.0!'
}
})
因?yàn)関ue2.0默認(rèn)的是runtime模式铡原,需要借助如 webpack 的 vue-loader 工具把 .vue 文件編譯成 JavaScript代碼;
解決方案 二(常規(guī)操作)
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = { //module.exports commonjs規(guī)范
entry: './src/main.js', // 項(xiàng)目的入口文件商叹,webpack會(huì)從main.js開(kāi)始燕刻,把所有依賴的js都加載打包
output: {
path: path.resolve(__dirname, './dist'), // 項(xiàng)目的打包文件路徑
publicPath: '/dist/', // 通過(guò)devServer訪問(wèn)路徑
filename: 'build.js' // 打包后的文件名
},
devServer: {
historyApiFallback: true,
overlay: true
},
resolve: { // 修改別名,import Vue from ‘vue’ 這行代碼被解析為 import Vue from ‘vue/dist/vue.esm.js
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
};
這個(gè)修改和上次是一樣的意思剖笙,不過(guò)相對(duì)雅觀很多...
解決方案 三
修改main.js的模式
- compiler 模式
// src/main.js
// compiler 模式
new Vue({
el: '#app',
})
2.runtime 模式
//runtime模式
new Vue({
render: h => h(App) // App.vue
}).$mount("#app")
將1換成2卵洗,但我們推薦使用方案二;
最后 頁(yè)面展示如下:
引入css和scss
webpack默認(rèn)支持的是js的模塊化,如果需要其他類型文件也支持模塊化開(kāi)發(fā)过蹂,則需要引入相應(yīng)的loader用以解析!
安裝相關(guān)依賴
npm i node-sass css-loader vue-style-loader sass-loader --save-dev
webpack.config.js 修改如下
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = { //module.exports commonjs規(guī)范
entry: './src/main.js', // 項(xiàng)目的入口文件十绑,webpack會(huì)從main.js開(kāi)始,把所有依賴的js都加載打包
output: {
path: path.resolve(__dirname, './dist'), // 項(xiàng)目的打包文件路徑
publicPath: '/dist/', // 通過(guò)devServer訪問(wèn)路徑
filename: 'build.js' // 打包后的文件名
},
devServer: {
historyApiFallback: true,
overlay: true
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{ // scss
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
}
]
}
};
此時(shí)scss 及 css都能在開(kāi)發(fā)中使用并且模塊化引入了
語(yǔ)法轉(zhuǎn)譯 ES6 => ES5
引入相關(guān)依賴 利用bable轉(zhuǎn)譯
npm i babel-core babel-loader babel-preset-env babel-preset-stage-3 --save-dev
其中 babel-preset-stage是不同階段語(yǔ)法提案的轉(zhuǎn)碼規(guī)則(共有4個(gè)階段)酷勺,選裝一個(gè),其中0最厲害
npm install --save-dev babel-preset-stage-0
npm install --save-dev babel-preset-stage-1
npm install --save-dev babel-preset-stage-2
npm install --save-dev babel-preset-stage-3
// .babelrc
{
"presets": [
["env", { "modules": false }],
"stage-3"
]
}
同時(shí)修改 webpack.config.js
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = { //module.exports commonjs規(guī)范
entry: './src/main.js', // 項(xiàng)目的入口文件本橙,webpack會(huì)從main.js開(kāi)始,把所有依賴的js都加載打包
output: {
path: path.resolve(__dirname, './dist'), // 項(xiàng)目的打包文件路徑
publicPath: '/dist/', // 通過(guò)devServer訪問(wèn)路徑
filename: 'build.js' // 打包后的文件名
},
devServer: {
historyApiFallback: true,
overlay: true
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{ // scss
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{ // 添加解析js的loader
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
};
此時(shí)我們修改main.js嘗試使用es6語(yǔ)法
// src/main.js
import Vue from 'vue';
// import Vue from 'vue/dist/vue.esm.js' // 解決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
// console.log('hello world');
const say = function () {
return new Promise((resolve, reject) => {
resolve('I am es6');
})
}
var app = new Vue({
el: '#app',
data: {
mess: 'Hello Vue@2.0!'
},
methods: {
updateData() {
say().then((res)=>{
this.mess = res;
});
},
},
created() {
this.updateData();
}
})
此時(shí)頁(yè)面輸出效果如下
雖然滿足我們使用了脆诉,那么接下來(lái)我們嘗試一下ES7支持與否
main.js修改如下:
import Vue from 'vue';
// import Vue from 'vue/dist/vue.esm.js' // 解決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
// console.log('hello world');
const say = function () {
return new Promise((resolve, reject) => {
resolve('I am es7');
})
}
var app = new Vue({
el: '#app',
data: {
mess: 'Hello Vue@2.0!'
},
methods: {
/*updateData() {
say().then((res)=>{
this.mess = res;
});
},*/
async updateData() {
const mess = await say();
this.mess = mess;
}
},
created() {
this.updateData();
}
})
頁(yè)面展示如下:
此時(shí)看到控制臺(tái)報(bào)錯(cuò)
"ReferenceError: regeneratorRuntime is not defined"
查閱相關(guān)文章發(fā)現(xiàn)甚亭, 要想對(duì)es7語(yǔ)法進(jìn)行支持,還需要安裝相關(guān)依賴進(jìn)行轉(zhuǎn)譯击胜;
這里有兩種方案
方案一
npm i --save-dev babel-plugin-transform-runtime
修改.babelrc文件
// .babelrc
{
"presets": [
["env", { "modules": false }],
"stage-3"
],
"plugins": [[ // 參考 http://www.reibang.com/p/7a7f7abcddb5
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
}
這里順帶解釋一下preset與babel的關(guān)系:
- preset中已經(jīng)包含了一組用來(lái)轉(zhuǎn)換ES6+的語(yǔ)法的插件,如果只使用少數(shù)新特性而非大多數(shù)新特性,可以不使用preset而只使用對(duì)應(yīng)的轉(zhuǎn)換插件
- babel默認(rèn)只轉(zhuǎn)換語(yǔ)法,而不轉(zhuǎn)換新的API,如需使用新的API,還需要使用對(duì)應(yīng)的轉(zhuǎn)換插件或者polyfill
例如亏狰,默認(rèn)情況下babel可以將箭頭函數(shù),class等語(yǔ)法轉(zhuǎn)換為ES5兼容的形式偶摔,但是卻不能轉(zhuǎn)換Map暇唾,Set,Promise等新的全局對(duì)象辰斋,這時(shí)候就需要使用polyfill去模擬這些新特性
此時(shí)看到頁(yè)面輸出正常:
方案二
全局babel-polyfill
npm i babel-polyfill --save-dev
webpack.config.js修改如下 注意看注釋
// webpack.config.js
// entry: './src/main.js', // 項(xiàng)目的入口文件策州,webpack會(huì)從main.js開(kāi)始,把所有依賴的js都加載打包
entry: ['babel-polyfill', './src/main.js'], // 項(xiàng)目的入口文件亡呵,webpack會(huì)從main.js開(kāi)始抽活,把所有依賴的js都加載打包 參考 http://www.reibang.com/p/3b27dfc6785c
此時(shí)重新跑項(xiàng)目npm run dev 結(jié)果方案一
es6與es7轉(zhuǎn)譯部分參考文章
babel-polyfill的幾種使用方式
babel的使用
文章最后
項(xiàng)目搭建,缺啥補(bǔ)啥C淌病! 項(xiàng)目完整地址查看@王一諾wlove_c/webpack4.0+vue2.0
2019年6月16日文章更新webpack代理配置
此次更新的原因是在一個(gè)技術(shù)分享群有同學(xué)問(wèn)到丁逝,當(dāng)時(shí)有點(diǎn)懵汁胆,webpack都更新到4.34.0了還有同學(xué)不會(huì)設(shè)置代理,所以借助這邊文章更新一下代理配置霜幼;
安裝依賴 webpack-dev-server
npm install webpack-dev-server --save-dev
實(shí)際上webpack是通過(guò)http-proxy-middleware來(lái)作方向代理解決跨域的,詳情有興趣的同學(xué)可以自己了解一下
修改配置如下
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = { //module.exports commonjs規(guī)范
...
devServer: {
historyApiFallback: true,
overlay: true,
proxy: {
'/api': {
target: 'http://localhost:3000', // 接口的域名和端口 如果端口為80則可以不寫
pathRewrite: {'^/api' : ''}, // 如果不是以api開(kāi)頭的可以清空
changeOrigin: true, // target是域名的話嫩码,需要這個(gè)參數(shù),
secure: false, // 默認(rèn)情況下罪既,不接受運(yùn)行在 HTTPS 上铸题,且使用了無(wú)效證書的后端服務(wù)器。如果你想要接受琢感,修改配置如下:
},
},
},
...
};
此時(shí)你跑項(xiàng)目的時(shí)候 npm run dev 時(shí) 你會(huì)發(fā)現(xiàn)丢间,請(qǐng)求到 /api/users 現(xiàn)在會(huì)被代理到請(qǐng)求 http://localhost:3000/api/users。并且不會(huì)有跨域問(wèn)題驹针!不過(guò)后端同學(xué)要允許跨域或者設(shè)置域名白名單喔
更多webpack-dev-server配置可以轉(zhuǎn)@webpack/devserver-proxy
如果你想要nginx作代理的話也是可以滴烘挫;詳情請(qǐng)轉(zhuǎn)我的另一篇文章@王一諾Eno的文章nginx部署/代理/跨域