2020年,你需要懂的webpack配置[入門篇]

時樾1998發表於2020-03-02

隨著前端工程化的越來越瘋狂,不會點webpack的前端真的吃不香,睡不著。

所謂webpack就是一個現代 JavaScript 應用程式的靜態模組打包器。

開胃菜

吃飯前先來一道開胃菜,看完這遍文章你會學到什麼?

  • 瞭解什麼是webpack
  • 知道怎麼去打包靜態資源
  • 知道幾個(entrt,output,module,plugins等)核心的配置作用
  • 不用vue-cli,從0到1跑起自己的vue專案
  • 不用create-react-app,從0到1跑起自己的react專案
  • 搭建一個既能跑vue專案也能跑react專案的配置

以上這些都是你將會學到的。

溫馨提示:建議跟著一起敲,這會加深你對每一個知識的理解和固定; 還有內容有點多,需要你靜下心來慢慢的品嚐,你會收穫到你意想不到的知識。

入門webpack

1.1初始化專案

先我們先在自己舒服的地方建立一個資料夾,資料夾裡面初始化專案。

    mkdir myWebpackPro
    npm init -y
複製程式碼

然後我們安裝webpack webpack-cli 到專案

npm i webpack webpack-cli -D
複製程式碼

你也可以用cnpm 或者yarn 來安裝

cnpm i webpack webpack-cli -D / yarn add webpack webpack-cli -D
複製程式碼

接著我們在myWebpack資料夾建立一個src資料夾,在裡面建立一個index.js檔案(這個將來將是我們的入口檔案)。

mkdir src
cd src
touch index.js
複製程式碼

最後我們在與src同級建立一個webpack.config.js(配置webpack的檔案)檔案

touch webpack.config.js
複製程式碼

最終的目錄結構是這樣的

2020年,你需要懂的webpack配置[入門篇]

到此為止,我們初始化專案就完成了。

1.2測試webpack能否正常打包

首先,我們在index.js裡面隨便**console.log()**一句

2020年,你需要懂的webpack配置[入門篇]

然後到package.jsonscript下配置一下build命令,先刪除預設的test命令,再新增build命令:

"build":"webpack ./src/index.js"
複製程式碼

2020年,你需要懂的webpack配置[入門篇]

最後我們再終端執行npm run build命令

npm run build
複製程式碼

如果執行成功的話在根目錄會多一個dist資料夾裡面會有一個main.js

2020年,你需要懂的webpack配置[入門篇]

讓我們開啟main.js看看有沒有把我們剛剛console.log()的那句話打包進去。

2020年,你需要懂的webpack配置[入門篇]

現在讓我們真正進入webpack配置。

1.3更改webpack的入口和預設打包的檔名

首先,我們開啟webpack.config.js配置一下entryoutput

2020年,你需要懂的webpack配置[入門篇]

我們在頂層引進path模組,這是node內建的一個模組,無需單獨安裝,是用來出來檔案路徑的一個模組。我們的打包入口(entry)依舊是剛剛建立的那個index.js檔案,出口(output)也就是打包成功後,輸出的位置(path)和檔名(filename),我們輸出的位置依舊選擇了dist檔案下,但是輸出的檔名,我們該為了index.js(之後我們會將檔名改為動態的)

配置完這些後,我們到package.json改一下打包路徑,將之前的./src/index.js改為./webpack.config.js

2020年,你需要懂的webpack配置[入門篇]

我們npm run build之後依舊能打包成功。

2020年,你需要懂的webpack配置[入門篇]

輸出的檔名也變成了index.js,現在你會看到dist目錄下還有個main.js,是不是感到很奇怪?不用奇怪,這是我們上一次打包餘留下來的,等下我們將來說如何解決上一次打包餘留下來的檔案。

1.4新建一個index.html模版

首先,我們在src下新建一個跑public資料夾,然後在裡面新建一個index.html模版(用於我們檢視打包的js檔案,之後再用於我們vue或者react專案的唯一html渲染模版)

cd src
mkdir public 
touch index.html
複製程式碼

新建完之後我們將剛才打包好的js引進去看看,瀏覽器有沒有列印出我們console.log()。

2020年,你需要懂的webpack配置[入門篇]

但是,當我們將outputfilename改成動態之後,每次打包輸出的檔名都不一樣,那麼我們每一次打包都要重新引用一次,這樣特別麻煩。

1.5html-webpack-plugin

為了解決上面說的那個問題,我們需要安裝一下html-webpack-plugin外掛。

npm run html-webpack-plugin -D
複製程式碼

安裝完之後我們在webpack.config.js配置一下plugins

2020年,你需要懂的webpack配置[入門篇]

這裡我們配置了html-webpack-plugin,也把輸入檔名改為了動態的了([name].[hash:8].js)。

我們再npm run build,然後你會看到再dist下多一個index.html。接著開啟它,發現控制檯輸出的跟我們console.log()的值一致就對了。(記得在打包前,把之前在index.html手機引進的script標籤去掉,不如打包會在控制檯會報一個找不到檔名的錯)

接下來,我們來解決,打包後自動清除之前打包的程式碼。

1.6 clean-webpack-plugin

現在你開啟dist好很多冗餘的js檔案,每次手動清除的話會非常煩躁。那我們就讓webpack來幫我們做。

2020年,你需要懂的webpack配置[入門篇]

首先,安裝clean-webpack-plugin

npm i clean-webpack-plugin -D
複製程式碼

安裝完之後,我們再配置一下plugins選項。

2020年,你需要懂的webpack配置[入門篇]

注意⚠️:CleanWebpackPlugin是具名匯出。

最後,我們在npm run build一下,看看dist目錄下還有沒有多餘的js檔案。

2020年,你需要懂的webpack配置[入門篇]

soga,乾淨。

那麼,現在問題又來,我們每次改動一點js程式碼都要重新手動去打包一次,這樣真炒雞麻煩啊,那有沒有自動打包的方法呢?那麼答案來咯,當然是有的。下面我們解決這個問題。

1.7 熱更新

現在我們來解決自動打包的問題。首先,我們安裝一下webpack-dec-server,配合webpack內建的HotModuleReplacementPlugin外掛來完成熱更新。

npm i webpack-dev-server -D
複製程式碼

HotModuleReplacementPlugin不用手動下載,webpack內建。

安裝完之後,我們先來配置一下webpack.config.js檔案

2020年,你需要懂的webpack配置[入門篇]

配置完webpack.config.js,我們的package.json新增一條打包命令

2020年,你需要懂的webpack配置[入門篇]

配置完後,我們現在用npm run dev命令打包,然後我們回去更新我們index.js檔案的任何東西,儲存之後都會自動更新。

好了,現在基礎功能,我們搭建得差不多了。接下我們配置module,繼續完善最後的基礎功能,比如打包js,css,image

1.8 打包js檔案

打包js檔案,主要是要將es6,7...的語法轉義成es5的語法,讓不相容es6,7...語法的瀏覽器也能使用。

首先我們先安裝一套包babel-loader,@babel/core,@babel/preset-env,@babel/polyfill

npm i babel-loader @babel/core @babel/preset-env @babel/polyfill -D
複製程式碼

安裝完之後,我們來配置webpack.config.jsmodule

2020年,你需要懂的webpack配置[入門篇]

這裡簡單介紹一下,每個loader的作用,babel-laoder主要是打包js檔案,而babel-loader又依賴@babel/core,@babel/preset-env可以轉義es6的map,every,fifler,some...語法,但是不轉義Promise,async,await...語法,所以要用@babel/polyfill來轉義。

1.9 打包css檔案

首先安裝幾個loader,style-loader,css-loader

npm i style-loader css-loader -D
複製程式碼

安裝完,我們接著配置module

2020年,你需要懂的webpack配置[入門篇]

這裡只是簡單配置css檔案,可能有些專案還會用到less,scss等,這裡就不過多闡述,如果你專案用到可以到官方找一下對應的loader配置一下,都是大同小異。

2.0 打包image,font,media檔案

首先還是先安裝幾個loader,url-laoder,file-loader

npm i url-loader file-loader -D
複製程式碼

安裝完,我們繼續配置module

2020年,你需要懂的webpack配置[入門篇]

介紹一下這兩個loader的配置,配置裡我們指定了limit,如果檔案沒有大於這個就用url-loader,base64打包,如果大過這個值,就會用file-loader打包,同時會按options下配置的name輸出到對應的位置。

好,基礎配置就說那麼多了,如果你的專案還有其他的需求可以到官網擼一番。

最終配置如下:


const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin')

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

const webpack = require('webpack')

const config = {

    entry: ['@babel/polyfill', path.resolve(__dirname, './src/index.js')],

    output: {

        filename: '[name].[hash:8].js',

        path: path.resolve(__dirname, './dist')

    },

    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_module/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.(jpg|png|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            fallback: {
                                loader: 'file-loader',
                                options: {
                                    name: 'img/[name].[hash:8].[ext]'
                                }
                            }
                        }
                    }
                ]
            },
            {
                test: /\.(mp4|webm|ogg|mp3|wav)(\?.*)?$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            fallback: {
                                loader: 'file-loader',
                                options: {
                                    name: 'media/[name].[hash:8].[ext]'
                                }
                            }
                        }
                    }
                ]
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            fallback: {
                                loader: 'file-loader',
                                options: {
                                    name: 'fonts/[name].[hash:8].[ext]'
                                }
                            }
                        }
                    }
                ]
            }
        ]
    },

    devServer: {
        port: '3000',
        host: '127.0.0.1',
        hot: true,
        open: true
    },

    plugins: [
        new HtmlWebpackPlugin({
            filename: "index.html",
            template: path.resolve(__dirname, './src/public/index.html')
        }),
        new CleanWebpackPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ]

}

module.exports = config
複製程式碼

從0到1跑起Vue專案

當你以上的基礎部分都熟悉了,我們從0到1搭建一個vue環境是soeasy的事。明人不說暗話,其實上面的基礎部分一直在為跑起vue專案做鋪墊。

現在我們要跑起vue專案,在以上基礎的配置上,在搞幾個loader就完事了,簡單得我都不好意思往下說了。

好了,現在我們先來安裝幾個東西,vue,vue-loader,vue-template-compiler,vuw-style-loader

npm i vue vue-loader vue-template-compiler vue-style-loader -D
複製程式碼

安裝完之後,我們來配置一下weback.config.js

這是module配置,記得在頂層匯入VueLoaderPlugin

2020年,你需要懂的webpack配置[入門篇]

這是plugins配置

2020年,你需要懂的webpack配置[入門篇]

配置完webpack.config.js之後,我們來在src下建立一個vue資料夾,然後在裡面建立一個app.vue檔案

cd src
mkdir vue
cd vue
touch App.vue
複製程式碼

目錄

2020年,你需要懂的webpack配置[入門篇]

接著在app.vue中,學上你熟悉的vue語法。

2020年,你需要懂的webpack配置[入門篇]

寫好之後,我們回到入口檔案也是src下的index,js,我們來重新寫一下里面的邏輯,之前只是console.log()一下,什麼也沒做。

最後我們的index.js檔案是這樣的。

2020年,你需要懂的webpack配置[入門篇]

這段程式碼對於用vue的同學再也熟悉不過來。

接著,我們回到src下的public下的index.html加一個根元素加上一個idroot

2020年,你需要懂的webpack配置[入門篇]

最後,我們npm run dev一下,我們的vue專案就跑起來了。

從0到1跑起React專案

我們搭建React專案的配置,還是重基礎配置上面配置。跑起react專案的配置比vue還要簡單。

首先,我們先安裝一些東西。react,react-dom,@babel/preset-react

npm i react react-dom @babel/preset-react -D
複製程式碼

安裝完後,我們配置一下webpack.config.js

它只需要配置一下module下的js項就ok了。

2020年,你需要懂的webpack配置[入門篇]

接著,我們去寫一下入口檔案(index.js)的邏輯。

2020年,你需要懂的webpack配置[入門篇]

這段程式碼對用react的同學也是熟悉不過的了。

index.html檔案也根vue寫的一樣。

2020年,你需要懂的webpack配置[入門篇]

最後,我們npm run dev一下,我們的react專案的跑起來了。

到這裡,我們自己搭建Vue專案環境配置和React專案環境配置都說完了。

那麼我們怎麼可以把Vue環境跟React環境統一在放下同一個環境下,在我們學Vue的時候用Vue環境,在我們寫React的時候用React環境,這是我們接下要做的。

一套配置,兩套環境,既可跑Vue,也可跑React

我們回頭觀察一下Vue的配置跟React的配置有哪裡不一致,哪裡是一致的。

同:

entry,output

2020年,你需要懂的webpack配置[入門篇]

image,font,media打包

2020年,你需要懂的webpack配置[入門篇]

devServer和部分Plugin

2020年,你需要懂的webpack配置[入門篇]
不同的有:

  • js的loader配置,vue沒有@babel/preset-ract
  • css的loader的配置,vue用的是vue-style-loader,react用的是style-loader
  • vue的loader,react配置沒有
  • plugin,vue多了一個VueLoaderPlugin,react沒有

好了,現在我們找出它們的異同之處了,那就好辦了。

我們需要用一個叫webapck-merge的外掛,我們安裝一下。

npm i webpack-merge -D
複製程式碼

安裝完之後,我們在webapck.config.js同級目錄下新建兩個檔案webpack.vue.js,webpack.react.js,來放它們兩者不同的配置。

touch webpack.vue.js
touch webpack.react.js
複製程式碼

接著我們來寫一下它們的不同配置。

webpack.vue.js

const merge = require('webpack-merge')

const webpackConfig = require('./webpack.config')

const VueLoaderPlugin  = require('vue-loader/lib/plugin')

const config = {
    module:{
        rules:[
            {
                test:/\.vue$/,
                use:['vue-loader']
            },
            {
                test: /\.js$/,
                exclude: /node_module/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['vue-style-loader', 'css-loader']
            },
        ]
    },
    plugins:[
        new VueLoaderPlugin()
    ]
}

module.exports = merge(webpackConfig,config)
複製程式碼

webpack.react.js

const merge = require('webpack-merge')

const webpackConfig = require('./webpack.config')

const config = {
    module:{
        rules:[
            {
                test: /\.js$/,
                exclude: /node_module/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: ['@babel/preset-react','@babel/preset-env']
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
        ]
    }
}

module.exports = merge(webpackConfig,config)

複製程式碼

最後webpack.config.js就成這樣了。


const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin')

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

const webpack = require('webpack')

const config = {

    entry: ['@babel/polyfill', path.resolve(__dirname, './src/index.js')],

    output: {

        filename: '[name].[hash:8].js',

        path: path.resolve(__dirname, './dist')

    },

    module: {
        rules: [      
            {
                test: /\.(jpg|png|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            fallback: {
                                loader: 'file-loader',
                                options: {
                                    name: 'img/[name].[hash:8].[ext]'
                                }
                            }
                        }
                    }
                ]
            },
            {
                test: /\.(mp4|webm|ogg|mp3|wav)(\?.*)?$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            fallback: {
                                loader: 'file-loader',
                                options: {
                                    name: 'media/[name].[hash:8].[ext]'
                                }
                            }
                        }
                    }
                ]
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            fallback: {
                                loader: 'file-loader',
                                options: {
                                    name: 'fonts/[name].[hash:8].[ext]'
                                }
                            }
                        }
                    }
                ]
            }
        ]
    },

    devServer: {
        port: '3000',
        host: '127.0.0.1',
        hot: true,
        open: true
    },

    plugins: [
        new HtmlWebpackPlugin({
            filename: "index.html",
            template: path.resolve(__dirname, './src/public/index.html')
        }),
        new CleanWebpackPlugin(),
        new webpack.HotModuleReplacementPlugin(),
    ]

}

module.exports = config
複製程式碼

好了,現在我們把它們的配置拆分完畢了,還剩最後一步我們就大功告成了,那就是在package.json新增兩條命令。

2020年,你需要懂的webpack配置[入門篇]

在我們寫vue專案的時候,我們就用npm run vue,在寫react專案的時候,我們就用npm run react

結尾

好了,到現在為止,我們把從基礎配置到vue到react再到合併兩套環境都做完了。原創不易,希望這篇文章能幫助到你。如果有不到位,歡迎在下面留言;如果把你看得睡著過去的,歡迎來找我,我給你暖被窩,哈哈哈;如果有把你說蒙的了或者還不明白的,歡迎來找我,我把我的剩餘的兩個口罩送一半給你。

2020年,你需要懂的webpack配置[入門篇]

相關文章