https://juejin.im/post/5e5a8cac6fb9a07cd942b396css
隨着前端工程化的愈來愈瘋狂,不會點webpack的前端真的吃不香,睡不着。html
今天.我決定手把手帶你入門webpack前端
所謂webpack就是一個現代 JavaScript 應用程序的靜態模塊打包器。vue
開胃菜
吃飯前先來一道開胃菜,看完這遍文章你會學到什麼?node
- 瞭解什麼是webpack
- 知道怎麼去打包靜態資源
- 知道幾個(entrt,output,module,plugins等)核心的配置做用
- 不用vue-cli,從0到1跑起本身的vue項目
- 不用create-react-app,從0到1跑起本身的react項目
- 搭建一個既能跑vue項目也能跑react項目的配置
以上這些都是你將會學到的。react
舒適提示:建議跟着一塊兒敲,這會加深你對每個知識的理解和固定; 還有內容有點多,須要你靜下心來慢慢的品嚐,你會收穫到你意想不到的知識。webpack
入門webpack
1.1初始化項目
先咱們先在本身舒服的地方建立一個文件夾,文件夾裏面初始化項目。es6
mkdir myWebpackPro
npm init -y
複製代碼
而後咱們安裝webpack webpack-cli 到項目web
npm i webpack webpack-cli -D
複製代碼
你也能夠用cnpm 或者yarn 來安裝vue-cli
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
複製代碼
最終的目錄結構是這樣的
![](http://static.javashuo.com/static/loading.gif)
到此爲止,咱們初始化項目就完成了。
1.2測試webpack可否正常打包
首先,咱們在index.js裏面隨便**console.log()**一句
![](http://static.javashuo.com/static/loading.gif)
而後到package.json的script下配置一下build命令,先刪除默認的test命令,再添加build命令:
"build":"webpack ./src/index.js" 複製代碼
![](http://static.javashuo.com/static/loading.gif)
最後咱們再終端執行npm run build命令
npm run build
複製代碼
若是執行成功的話在根目錄會多一個dist文件夾裏面會有一個main.js
![](http://static.javashuo.com/static/loading.gif)
讓咱們打開main.js看看有沒有把咱們剛剛console.log()的那句話打包進去。
![](http://static.javashuo.com/static/loading.gif)
如今讓咱們真正進入webpack配置。
1.3更改webpack的入口和默認打包的文件名
首先,咱們打開webpack.config.js配置一下entry和output
![](http://static.javashuo.com/static/loading.gif)
咱們在頂層引進path模塊,這是node內置的一個模塊,無需單獨安裝,是用來出來文件路徑的一個模塊。咱們的打包入口(entry)依舊是剛剛建立的那個index.js文件,出口(output)也就是打包成功後,輸出的位置(path)和文件名(filename),咱們輸出的位置依舊選擇了dist文件下,可是輸出的文件名,咱們該爲了index.js(以後咱們會將文件名改成動態的)
配置完這些後,咱們到package.json改一下打包路徑,將以前的./src/index.js改成./webpack.config.js
![](http://static.javashuo.com/static/loading.gif)
咱們npm run build以後依舊能打包成功。
![](http://static.javashuo.com/static/loading.gif)
輸出的文件名也變成了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()。
![](http://static.javashuo.com/static/loading.gif)
可是,當咱們將output的filename改爲動態以後,每次打包輸出的文件名都不同,那麼咱們每一次打包都要從新引用一次,這樣特別麻煩。
1.5html-webpack-plugin
爲了解決上面說的那個問題,咱們須要安裝一下html-webpack-plugin插件。
npm run html-webpack-plugin -D
複製代碼
安裝完以後咱們在webpack.config.js配置一下plugins。
![](http://static.javashuo.com/static/loading.gif)
這裏咱們配置了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來幫咱們作。
![](http://static.javashuo.com/static/loading.gif)
首先,安裝clean-webpack-plugin。
npm i clean-webpack-plugin -D
複製代碼
安裝完以後,咱們再配置一下plugins選項。
![](http://static.javashuo.com/static/loading.gif)
注意⚠️:CleanWebpackPlugin是具名導出。
最後,咱們在npm run build一下,看看dist目錄下還有沒有多餘的js文件。
![](http://static.javashuo.com/static/loading.gif)
soga,乾淨。
那麼,如今問題又來,咱們每次改動一點js代碼都要從新手動去打包一次,這樣真炒雞麻煩啊,那有沒有自動打包的方法呢?那麼答案來咯,固然是有的。下面咱們解決這個問題。
1.7 熱更新
如今咱們來解決自動打包的問題。首先,咱們安裝一下webpack-dec-server,配合webpack內置的HotModuleReplacementPlugin插件來完成熱更新。
npm i webpack-dev-server -D
複製代碼
HotModuleReplacementPlugin不用手動下載,webpack內置。
安裝完以後,咱們先來配置一下webpack.config.js文件
![](http://static.javashuo.com/static/loading.gif)
配置完webpack.config.js,咱們的package.json添加一條打包命令
![](http://static.javashuo.com/static/loading.gif)
配置完後,咱們如今用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.js的module。
![](http://static.javashuo.com/static/loading.gif)
這裏簡單介紹一下,每一個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-laoder css-loader -D
複製代碼
安裝完,咱們接着配置module
![](http://static.javashuo.com/static/loading.gif)
這裏只是簡單配置css文件,可能有些項目還會用到less,scss等,這裏就不過多闡述,若是你項目用到能夠到官方找一下對應的loader配置一下,都是大同小異。
2.0 打包image,font,media文件
首先仍是先安裝幾個loader,url-laoder,file-loader。
npm i url-loader file-loader -D
複製代碼
安裝完,咱們繼續配置module
![](http://static.javashuo.com/static/loading.gif)
介紹一下這兩個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-laoder vue-template-compiler vue-style-loader -D
複製代碼
安裝完以後,咱們來配置一下weback.config.js
這是module配置,記得在頂層導入VueLoaderPlugin
![](http://static.javashuo.com/static/loading.gif)
這是plugins配置
![](http://static.javashuo.com/static/loading.gif)
配置完webpack.config.js以後,咱們來在src下建立一個vue文件夾,而後在裏面建立一個app.vue文件
cd src mkdir vue cd vue touch App.vue 複製代碼
目錄
![](http://static.javashuo.com/static/loading.gif)
接着在app.vue中,學上你熟悉的vue語法。
![](http://static.javashuo.com/static/loading.gif)
寫好以後,咱們回到入口文件也是src下的index,js,咱們來從新寫一下里面的邏輯,以前只是console.log()一下,什麼也沒作。
最後咱們的index.js文件是這樣的。
![](http://static.javashuo.com/static/loading.gif)
這段代碼對於用vue的同窗再也熟悉不過來。
接着,咱們回到src下的public下的index.html加一個根元素加上一個id爲root。
![](http://static.javashuo.com/static/loading.gif)
最後,咱們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了。
![](http://static.javashuo.com/static/loading.gif)
接着,咱們去寫一下入口文件(index.js)的邏輯。
![](http://static.javashuo.com/static/loading.gif)
這段代碼對用react的同窗也是熟悉不過的了。
index.html文件也根vue寫的同樣。
![](http://static.javashuo.com/static/loading.gif)
最後,咱們npm run dev一下,咱們的react項目的跑起來了。
到這裏,咱們本身搭建Vue項目環境配置和React項目環境配置都說完了。
那麼咱們怎麼能夠把Vue環境跟React環境統一在放下同一個環境下,在咱們學Vue的時候用Vue環境,在咱們寫React的時候用React環境,這是咱們接下要作的。
一套配置,兩套環境,既可跑Vue,也可跑React
咱們回頭觀察一下Vue的配置跟React的配置有哪裏不一致,哪裏是一致的。
同:
entry,output
![](http://static.javashuo.com/static/loading.gif)
image,font,media打包
![](http://static.javashuo.com/static/loading.gif)
devServer和部分Plugin
![](http://static.javashuo.com/static/loading.gif)
- 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添加兩條命令。
![](http://static.javashuo.com/static/loading.gif)
在咱們寫vue項目的時候,咱們就用npm run vue,在寫react項目的時候,咱們就用npm run react。
結尾
好了,到如今爲止,咱們把從基礎配置到vue到react再到合併兩套環境都作完了。原創不易,但願這篇文章能幫助到你。若是有不到位,歡迎在下面留言;若是把你看得睡着過去的,歡迎來找我,我給你暖被窩,哈哈哈;若是有把你說蒙的了或者還不明白的,歡迎來找我,我把個人剩餘的兩個口罩送一半給你。
最後,我還想問各位大佬一下這句話什麼意思,一個朋友發給個人:"油城壯志憶往昔,秋風吹葉道難行。莫問前路多迷茫,龍門躍起終識君"。我百度了也沒有這首詩啊🤣。
![](http://static.javashuo.com/static/loading.gif)