都8102年了,如今還來談webpack的配置,額,是有點晚了。並且,基於vue-cli或者create-react-app生成的項目,也已經一鍵爲咱們配置好了webpack,看起來彷佛並不須要咱們深刻了解。javascript
不過,爲了學習和理解webpack解決了前端的哪些痛點,仍是有必要從零開始本身搭建一個簡單的開發環境。本文的webpack配置參考了vue-cli提供webpack-simple
模板,這也是vue-cli裏面最簡單的一個webpack配置,很是適合從零開始學習。css
注: 本文webpack基於3.10.0html
npm i webpack -g
複製代碼
新建一個文件夾vue-webpack-simple前端
新建package.jsonvue
npm init -y
複製代碼
安裝vue webpack webpack-dev-serverjava
npm i vue --save
複製代碼
npm i webpack webpack-dev-server --save-dev
複製代碼
根目錄下新建index.htmlnode
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
複製代碼
根目錄下新建webpack.config.jsreact
var path = require('path');
var webpack = require('webpack');
module.exports = {};
複製代碼
新建src文件夾,src文件夾下新建main.jswebpack
目前整個項目的結構以下: git
在ES6出現以前,js是沒有統一的模塊體系。 服務器端使用CommonJS規範,而瀏覽器端又有AMD和CMD兩種規範
webpack的思想就是一切皆模塊,官方推薦使用commonJS規範,這使得咱們瀏覽器端也可使用commonJS的模塊化寫法
module.exports = {}
複製代碼
src目錄下新建一個util.js
module.exports = function say() {
console.log('hello world');
}
複製代碼
main.js
var say = require('./util');
say();
複製代碼
修改webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/main.js', // 項目的入口文件,webpack會從main.js開始,把全部依賴的js都加載打包
output: {
path: path.resolve(__dirname, './dist'), // 項目的打包文件路徑
publicPath: '/dist/', // 經過devServer訪問路徑
filename: 'build.js' // 打包後的文件名
},
devServer: {
historyApiFallback: true,
overlay: true
}
};
複製代碼
修改package.josn
"scripts": {
"dev": "webpack-dev-server --open --hot",
"build": "webpack --progress --hide-modules"
},
複製代碼
注意:webpack-dev-server會自動啓動一個靜態資源web服務器 --hot參數表示啓動熱更新
修改index.html,引入打包後的文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="/dist/build.js"></script>
</body>
</html>
複製代碼
運行
npm run dev
複製代碼
能夠發現瀏覽器自動打開的一個頁面,查看控制檯,有hello world
打出
咱們隨意修改util.js,能夠發現瀏覽器會自動刷新,很是方便。
若是咱們但願看打包後的bundle.js文件,運行
npm run build
複製代碼
能夠看到生成了一個dist目錄,裏面就有打包好後的bundle.js
webpack默認不支持轉碼es6,可是import
export
這兩個語法卻單獨支持。因此咱們能夠改寫前面的模塊化寫法
util.js
export default function say() {
console.log('hello world ');
}
複製代碼
main.js
import say from './util';
say();
複製代碼
下面咱們來試着引入vue(目前不考慮單文件.vue)
main.js
import Vue from 'vue';
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
複製代碼
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
{{message}}
</div>
<script src="/dist/build.js"></script>
</body>
</html>
複製代碼
還要注意一點:要修改webpack.config.js文件
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
devServer: {
historyApiFallback: true,
overlay: true
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
};
複製代碼
從新運行npm run dev,能夠看到,頁面正常顯示了Hello World
webpack默認只支持js的模塊化,若是須要把其餘文件也當成模塊引入,就須要相對應的loader解析器
npm i node-sass css-loader vue-style-loader sass-loader --save-dev
複製代碼
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
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'
],
}
]
}
};
複製代碼
解釋:
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}
複製代碼
這段代碼意思是:匹配後綴名爲css的文件,而後分別用css-loader,vue-style-loader去解析 解析器的執行順序是從下往上(先css-loader再vue-style-loader)
注意:由於咱們這裏用vue開發,因此使用vue-style-loader,其餘狀況使用style-loader
css-loader使得咱們能夠用模塊化的寫法引入css,vue-style-loader會將引入的css插入到html頁面裏的style標籤裏
要引入scss也是同理的配置寫法:
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
],
}]
}
複製代碼
咱們如今來試下 在src目錄下新建style目錄,style目錄裏新建common.scss
body {
background: #fed;
}
複製代碼
main.js
import './style/common.scss';
複製代碼
發現css樣式有用了
ES6的語法大多數瀏覽器依舊不支持,bable能夠把ES6轉碼成ES5語法,這樣咱們就能夠大膽的在項目中使用最新特性了
npm i babel-core babel-loader babel-preset-env babel-preset-stage-3 --save-dev
複製代碼
在項目根目錄新建一個.babelrc文件
{
"presets": [
["env", { "modules": false }],
"stage-3"
]
}
複製代碼
webpack.config.js添加一個loader
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
複製代碼
exclude表示忽略node_modules文件夾下的文件,不用轉碼
如今咱們來試下async await語法吧 util.js
export default function getData() {
return new Promise((resolve, reject) => {
resolve('ok');
})
}
複製代碼
main.js
import getData from './util';
import Vue from 'vue';
import './style/common.scss';
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods: {
async fetchData() {
const data = await getData();
this.message = data;
}
},
created() {
this.fetchData();
}
});
複製代碼
這時控制檯會報一個錯誤regeneratorRuntime is not defined
,由於咱們沒有安裝babel-polyfill
npm i babel-polyfill --save-dev
複製代碼
而後修改webpack.config.js的入口
entry: ['babel-polyfill', './src/main.js'],
複製代碼
從新npm run dev,能夠發現正常運行了
把圖片也當成模塊引入
npm i file-loader --save-dev
複製代碼
webpack.config.js添加一個loader
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
複製代碼
在src目錄下新建一個img目錄,存放一張圖片logo.png
修改main.js
import getData from './util';
import Vue from 'vue';
import './style/common.scss';
Vue.component('my-component', {
template: '<img :src="url" />',
data() {
return {
url: require('./img/logo.png')
}
}
})
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue !'
},
methods: {
async fetchData() {
const data = await getData();
this.message = data;
}
},
created() {
this.fetchData()
}
});
複製代碼
修改index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
{{message}}
<my-component/>
</div>
<script src="/dist/build.js"></script>
</body>
</html>
複製代碼
能夠看見,圖片也被正確加載了
在前面的例子裏,咱們使用 Vue.component 來定義全局組件 在實際項目裏,更推薦使用單文件組件
npm i vue-loader vue-template-compiler --save-dev
複製代碼
添加一個loader
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
],
'sass': [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
]
}
}
}
複製代碼
在src目錄下新建一個App.vue
<template>
<div id="app">
<h1>{{ msg }}</h1>
<img src="./img/logo.png">
<input type="text" v-model="msg">
</div>
</template>
<script> import getData from './util'; export default { name: 'app', data () { return { msg: 'Welcome to Your Vue.js' } }, created() { this.fetchData(); }, methods: { async fetchData() { const data = await getData(); this.msg = data; } } } </script>
<style lang="scss"> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; h1 { color: green; } } </style>
複製代碼
main.js
import Vue from 'vue';
import App from './App.vue';
import './style/common.scss';
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
複製代碼
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="/dist/build.js"></script>
</body>
</html>
複製代碼
npm run dev,能夠發現單文件被正確加載了
在開發階段,調試也是很是重要的一項需求。
App.vue
created() {
this.fetchData();
console.log('23333');
}
複製代碼
咱們故意打一個console,打開控制檯
咱們點擊進入這個console的詳細地址
進入的是打包後的build.js,我並不知道是在哪一個組件裏寫的,這就形成了調試困難
這時就要修改webpack.config.js
module.exports = {
entry: ['babel-polyfill', './src/main.js'],
// 省略其餘...
devtool: '#eval-source-map'
};
複製代碼
從新npm run dev
咱們先試着npm run build打包一下文件
會發現,打包後的build.js很是大,有500多k了
在實際發佈時,會對文件進行壓縮,緩存,分離等等優化處理
npm i cross-env --save-dev
複製代碼
修改package.json
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
複製代碼
此次咱們設置了環境變量,打包時,NODE_ENV是production
而後修改webpack.config.js,判斷NODE_ENV爲production時,壓縮js代碼
var path = require('path');
var webpack = require('webpack');
module.exports = {
// 省略...
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map';
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin(),
])
}
複製代碼
從新打包
能夠看見,壓縮效果很是明顯!
至此,一個很是簡單的vue開發環境搭建成功。
注意:本文中的配置還有很是多能夠優化的地方,好比分離js和css
讀者能夠自行了解相關知識,這裏只是帶領你們瞭解最基礎的webpack配置。