mkdir webpack-demo
javascript
cd webpack-demo
css
npm init
html
// package.json
{
+"private":true// 表明該文件不會被髮布到npm倉庫上去
-"main":"index.js",//由於只是本身使用,因此不須要向外暴露入口文件
}
複製代碼
npm install webpack webpack-cli -D
java
在項目內安裝webpack而不是在全局安裝webpack,能夠保證不一樣項目依賴不一樣版本的webpack而不會出錯node
此時終端輸入webpack
,會提示找不到webpack ,這是由於node會去全局的目錄尋找webpackwebpack
咱們可使用npx webpack
,npx會幫助咱們在當前文件夾內尋找相應的安裝包css3
在沒有寫webpack的配置文件時,執行npx webpack index.js
,webpack會根據默認配置幫咱們進行打包web
但當咱們新建一個webpack.config.js
文件時,webpack則會根據咱們寫的配置文件進行打包npm
//webpack.config.js
const path. = require('path');
module.exports = {
mode:'production',//打包的模式。生產環境下會壓縮代碼,development則不糊壓縮
entry:'./index.js',// 入口文件
output:{
filename:'bundle.js',//打包後的文件名
path:path.resolve(__dirname,'bundle')// 打包後的 文件目錄
}
}
複製代碼
指定webpack以哪一個配置文件來打包json
npx webpack --config 文件名.js
簡化打包的命令行指令
//package.json
{
"scripts":{
"bundle":"webpack"//以後執行命令行npm run bundle === npx webpack
}
}
複製代碼
Hash: 本次打包對應的惟一一個hash值
Version: 本次打包對應的webpack的版本號
Time: 打包的時間
Asset: 打包出的文件名
Size: 打包後的文件大小
Chunks: 存放文件的ID值,若是bundle.js 跟a文件有關聯,則會在此處記錄bundle文件和a文件的ID值
Chunk Name: 存放文件自己與關聯文件的名字
Entrypoint: 入口文件是哪個
列舉打包的源文件
//index.js
import avatar from './avatar.jpg'
console.log(avatar)//avatar132425454.jpg
複製代碼
webpack默認是能夠打包j s文件的,但對於怎麼打包圖片確實不知道的,因此咱們須要在配置文件中告訴webpack怎麼去打包圖片,這就須要用到loader,loader就是一個打包的方案
npm install file-loader
//webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\.jpg$/,
use:{
loader:'file-loader'
}
}
]
}
}
複製代碼
打包完後,會發現圖片的名字改變了,若是想讓圖片的名字不改變,咱們能夠給file-loader添加參數
// webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\.(jpg|png|gif)$/ //對以jpg,png,gif結尾的文件進行打包
use:{
loader:'file-loader',
options:{
name:'[name]_[hash].[ext]',
//[name]是源文件的名字,[hash]是哈希值,不須要能夠刪除,[ext]是源文件的後綴名
outputPath:'images/' //打包到哪一個目錄文件下
}
}
}
]
}
}
複製代碼
與file-loader類似的還有url-loader
npm install url-loader -D
//webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\.(jpg|png|gif)$/
use:{
loader:'url-loader',
options:{
name:'[name].[ext]',
outputPath:'images/'
}
}
}
]
}
}
複製代碼
對比file-loader和url-loader打包後的輸出目錄
咱們會發現,頁面仍然是正常展現圖片的,但file-loader打包後,圖片的一個單獨的文件放在輸出目錄中,而url-loader打包後,則是將圖片變爲base64格式存放在bundle.js文件中
url-loader的優勢:減小了加載圖片的網絡請求,缺點,圖片過大時,會影響js文件的加載速度
解決,設置一個圖片大小的閥值 limit
options:{
name:'[name].[ext]',
outputPath:'images/',
limit:2048 //單位字節
}
複製代碼
當圖片大小大於2048字節時,就會輸出爲單獨的文件,小於2048字節時,就會以base64格式存放在bundle.js中
//index.js
import './index.css'
複製代碼
當咱們在js文件中引入c s s文件時,webpack打包時會提示錯誤,這時候就須要loader來幫忙了
npm install style-loader css-loader -D
//webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
}
}
複製代碼
那css-loader和style-loader的做用分別是什麼呢
css-loader負責處理css文件之間的關係
/*a.css*/
body{
background-color:blue
}
複製代碼
/*b.css*/
import './a.css'
複製代碼
//index.js
import './b.css'
複製代碼
style-loader則是將解析完畢的css掛載到header中
npm install style-loader css-loader sass-loader node-sass
module.exports = {
module:{
rules:[
{
test:/.scss$/,
use:['style-loader','css-loader','sass-loader'],
}
]
}
}
複製代碼
注意loader是從下到上,從右到左到順序,便是有順序的
npm install postcss-loader autoprefixer -D
在根目錄下新建文件postcss.config.js
//postcss.config.js
module.exports = {
plugins:[
require('autoprefixer')
]
}
複製代碼
//webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\scss$/,
use:['style-loader','css-loader','sass-loader','postcss-loader']
}
]
}
}
複製代碼
module.exports = {
module:{
rules:[
'style-loader',
{
loader:'css-loader',
options:{
importLoaders:2
}
},
'sass-loader',
'postcss-loader'
]
}
}
複製代碼
importLoaders:2指引入的sass文件也要去執行posts-loader和sass-loader
/*index.scss*/
import './a.scss'
body{
#root{
color:red;
}
}
複製代碼
/*a.scss*/
...
複製代碼
//index.js
import './index.scss'
複製代碼
webpack去解析index.scss時會通過postcss-loader,sass-loader,css-loader,接着會去解析引入的a.scss,若是咱們但願引入的的a.scss也要通過postcss-loader,sass-loader時,就要在cs s-loader的options參數中加上importloaders:2
/*a.scss*/
body{
.title{
color:red
}
}
複製代碼
// index.js
import './a.scss'
複製代碼
當我全局引入a.scss文件時,就會使得全局的title類名的元素文字顏色都變爲紅色。
因而咱們要引入一個css模塊化概念
//webpack.config.js
module.exports = {
module:{
rules:[
{
test:/\.scss$/,
use:[
'style-loader',
{
loader:'css-loader',
options:{
importLoaders:2,
modules:true,// 變爲模塊化打包
}
},
'sass-loader',
'postcss-loader'
]
}
]
}
}
複製代碼
//index.js
import style from './a.scss'
var span = document.createElement('span')
span.innerText='你好'
span.classList.add(style.title)//樣式只會影響這個元素,而其餘類名爲title元素則不會受影響
var root = document.getElementById('root')
root.append(span)
複製代碼
每次打包文件,咱們都須要在dist文件夾中新建一個html文件,而後引入打包後的j s文件,這是很是麻煩的
如今咱們推薦使用
html-webpack-plugin
使得打包更便捷
npm install -D htm-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins:[
new HtmlWebpaclPlugin()
]
}
複製代碼
htmlwebpackplugin會在打包結束後,自動生成一個html文件,並把打包生成的js自動引入到這個html文件中
打包後,咱們會發現webpack自動生成的html文件缺乏一個id爲root的div
若是咱們但願webpack打包後自動生成一個id爲root的div,咱們能夠給HtmlWebpackPlugin一個模版
//webpack.config.js
module.exports = {
plugins:[
new HtmlWebpackPlugin({
template:'src/index.html'//模版文件
})
]
}
複製代碼
plugin能夠在webpack運行到某個時刻的時候,幫你作一些事情
npm install -D clean-webpack-plugin
//webpack.config.js
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
plugins:[
new HtmlWebpackPlugin({
template:'src/index.html'
}),
new CleanWebpackPlugin()
]
}
複製代碼
module.exports = {
entry:{
key1:path1,
key2:path2
}
output:{
filename:xxx.js
path:path.resolve(__dirname,'dist')
}
}
複製代碼
key1與key2,表明打包輸出的文件名,path1與path2表明要打包文件的路徑
filename也表明打包輸出的文件名,單filename與key衝突時,會報錯,當有兩個key,而filename只有一個時,也會報錯,建議修改以下
module.exports = {
entry:{
main:'./src/main.js',
other:'./scr/other.js'
},
output:{
filename:'[name].js'//用[name]做爲佔位符,這樣打包輸出的文件名就會是entry中的key值
path:path.resolve(__dirname,'dist')
}
}
複製代碼
有時代碼寫錯了,控制檯報錯,會指出打包後的文件的哪一行代碼錯誤,但咱們想知道的是src目錄下的哪一個文件的哪行代碼錯誤。這時候就須要
sourceMap
module.exports = {
devtool:'source-map'
}
複製代碼
sourceMap其實就是一個映射關係
devtool | build | rebuild | production | quality |
---|---|---|---|---|
(none) | fastest | fastest | yes | bundled code |
eval | fastest | fastest | no | generated code |
cheap-eval-source-map | fast | faster | no | transformed code (lines only) |
cheap-module-eval-source-map | slow | faster | no | original source (lines only) |
eval-source-map | slowest | fast | no | original source |
cheap-source-map | fast | slow | yes | transformed code (lines only) |
cheap-module-source-map | slow | slower | yes | original source (lines only) |
inline-cheap-source-map | fast | slow | no | transformed code (lines only) |
inline-cheap-module-source-map | slow | slower | no | original source (lines only) |
source-map | slowest | slowest | yes | original source |
inline-source-map | slowest | slowest | no | original source |
hidden-source-map | slowest | slowest | yes | original source |
nosources-source-map | slowest | slowest | yes | without source content |
開發環境建議這麼配置
module.exports = {
devtool:'cheap-module-eval-source-map'
}
複製代碼
生產環境
module.exports = {
devtool:'cheap-module-source-map'
}
複製代碼
每次改完代碼,都要打包後,再去刷新瀏覽器,這樣比較麻煩
咱們但願能夠改完代碼後,webpack自動打包,而後自動刷新瀏覽器
想實現這樣的功能,有兩個方法
1
{
"scripts":{
"watch":"webpack --watch"//webpack會去監聽要打包的文件,當文件發生變化,就會自動去打包
}
}
複製代碼
2
npm install -D webpack-dev-server
藉助WebpackDevServer
來監聽文件變化並打包,自動打開並刷新瀏覽器
//webpack.config.js
module.exports = {
devServer:{
contentBase:'./dist'//服務器的根路徑就是在dist目錄下,
open:true,//會自動打開瀏覽器,並去訪問相應的服務器
proxy:{
'/api','http://localhost:3000'//支持跨域,當訪問api時,會轉發到localhost:3000
}
}
}
複製代碼
{
"scripts":{
"start":'webpack-dev-server'
}
}
複製代碼
使用webpack-dev-server 時。你會發現,如今沒有dist目錄了 ,這是由於webpack-dev-server將打包後後的文件放在了電腦的緩存中
當咱們改變樣式代碼時,瀏覽器會刷新,以前的狀態就會消失,這不是咱們想要的,咱們但願,咱們改變樣式代碼時,瀏覽器不會自動刷新
// index.js
import './index.css'
var btn = document.createElement('div')
btn.innerText = '點擊我'
btn.onclick = ()=>{
var div = document.createElement('div')
div.classList.add('item')
div.innerText='item'
document.body.appendChild(div)
}
複製代碼
.item:nth-of-type(odd){
color:red
}
複製代碼
點擊幾回,就會出現多個item
這時,咱們去將index.css文件中的color變爲blue時
瀏覽器會自動刷新,致使以前的狀態消失,這不是咱們要的,因此須要熱模塊更新
//webpack.config.js
const webpack = require('webpack')
module.exports = {
devServer:{
contentBase:'./dist',
open:true,
port:8080,
hot:true,//熱模塊替換
hotOnly:true,//即便html不生效,瀏覽器也不自動刷新,能夠不加
},
plugins:[
new webpack.HotModuleReplacementPlugin()
]
}
複製代碼
js代碼的熱更新
//a.js
var num = 0;
function number(){
var btn = document.createElement('div')
btn.setAttribute('id','number')
btn.innerText = num;
btn.onclick = ()=>{
num++1;
btn.innerText = num
}
document.body.appendChild(btn)
}
export default number;
複製代碼
//b.js
function show (){
var div = document.createElement('div')
div.innerText = '歡迎'
document.body.appendChild(div)
}
export default show
複製代碼
//index.js
import number from './a'
import show from './b'
show()
number()
複製代碼
//webpack.config.js
module.exports = {
devServer:{
hot:true,
contentBase:'./dist',
}
}
複製代碼
咱們把數字點擊到6,而後去修改b.js的代碼,歡迎改成再見
瀏覽器會從新刷新,以前的全部狀態所有沒有了。想要只刷改變的那一部分,應該這樣寫
//index.js
import number from './a'
import show from './b'
show()
number()
if(module.hot){// 監測熱更新,
module.hot.accept('./a',()=>{
//先刪除以前的dom
ducument.body.removeChild(document.getElementById('number'))
//再從新執行一次
number()
})
}
複製代碼
若是以爲文章不錯,請點個贊,有錯漏處,還請各位看官指正
若是要轉載,請註明出處
做者:胡志武
時間:2019/11/25