這是我花了幾個星期學習webpack4的學習筆記。內容不夠細,由於一些相對比較簡單的,就隨意帶過了。但願文章能給你們帶來幫助。若有錯誤,但願及時指出。例子都在learn-webpack倉庫上。若是你從中有所收穫的話,但願你能給個人github
點個star
。javascript
npm info webpack
查看webpack的歷史版本信息等npm init -y
跳過那些選項,默認
全局安裝的webpack
: webpack index.js
打包
項目中安裝的webpack
: npx webpack index.js
打包script
中腳本打包 : npm run build
命令行中打包:npx webpack index.js -o bundle.js
入口是index.js
, 出口是bundle.js
webpack4
設置mode:production
會壓縮代碼 development
就不壓縮代碼
打包 output
裏面[name].js loader
中的name
變量 其實就是entry:{main: index.js} 中的key => main
css
devtool: source-map
source-map
: dist
文件夾裏會多生成個map
後綴文件,這樣頁面報錯的時候,點擊報錯後面的地址,會跳轉到代碼寫的地方。而不會跳轉到打包後的代碼裏。inline-source-map
: 不會新生成.map文件,會插入到打包的文件底部cheap-inline-source-map
: 由於inline-source-map
報錯會告訴你第幾行第幾個字符。前面加上cheap
的話 只會告訴你第幾行cheap-module-inline-source-map
: 原本map只會映射打包出來的index.js跟業務代碼中的關係。第三方引入庫報錯映射不到。中間加了module這個參數就能夠了。好比loader
也會有source-map
開發的時候建議使用:cheap-module-eval-source-map
,eval
表示不會獨立生成map文件,而是打包進代碼裏。
通常development
環境用 cheap-module-eval-source-map
production
環境用cheap-module-source-map
html
// style.css body { color: red; }
當你想給項目添加樣式的時候,import ./style.css
導入css
,並執行打包命令的時候。頁面並報錯vue
ERROR in ./style.css 1:5 Module parse failed: Unexpected token (1:5) You may need an appropriate loader to handle this file type.
這個時候就須要使用loader
來編譯了。
安裝:npm i style-loader css-loader -D
爲何還須要安裝style-loader
呢?由於style-loader
會將你的樣式經過style
標籤插入到頁面中
配置webpack.config.js
java
// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode: "development", entry: './index.js', output: { filename: 'bundle.js' }, module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin() ] }
上面使用了HtmlWebpackPlugin
是由於我用它來自動生成index.html
方便頁面訪問node
// package.json "scripts": { "build": "webpack --config webpack.config.js" },
執行npm run build
進行打包,訪問dist
目錄下的index.html
,能夠看到頁面顯示成功。loader
執行順序是從下到上,右到左。react
webpack-dev-server
會對你的代碼進行打包,將打包的內容放到內存裏面,並不會自動給你打包放進dist裏。
webpack —watch
頁面會刷新下,內容會自動更新
webpack-dev-server
會自動更新當前頁面
webpack-dev-server
, 如今的webpack-dev-server
比之前好多了vue-cli3
和react
都是用這個了
devServer: { contentBase: './dist', // 有這個就夠了, open: true, // 自動打開瀏覽器 port: 8080, // 端口沒必要填 proxy: {'/api': http://localhost:3000} }
npm install express webpack-dev-middleware -D
在output
中添加publicPath
webpack
const express = require('express') const webpack = require('webpack') const webpackDevMiddleWare = require('webpack-dev-middleware') const config = require('./webpack.config.js') const complier = webpack(config) // 幫咱們作編譯的東西,webpack傳入config以後會申請一個編譯器 app.use(webpackDevMiddleware(complier, { publicPath: config.output.publicPath, // 意思是隻要文件改變了,就從新運行 })) const app = express() app.listen(3000, () => { console.log('server is running 3000') })
如今這樣子寫太麻煩了(vue-cli2也是如此)。由於之前版本
webpack-dev-server
還不夠強大,如今不同了。很是的強大了。
熱替換,就是不會刷新整個頁面。當不使用熱更新的時候,操做一些功能,新增了三個元素,修改樣式頁面自動刷新後,剛纔新增的元素會消失。若是開啓了熱替換,那麼原先的dom會還在。
const webpack = require('webpack') // .... devServer: { contentBase: './dist', open: true, hot: true, hotOnly: true // 以防hot失效後,頁面被刷新,使用這個,hot失效也不刷新頁面 }, // ... plugins: [ new webpack.HotModuleReplacementPlugin() ]
import number from './number.js' if (module.hot) { // 若是熱更新存在 // 監聽的文件改變,會觸發後面的回調方法 module.hot.accept('./number', () => { // dosomething }) }
爲何修改了css文件不須要寫module.hot。而寫js須要寫呢,由於css-loader已經自動幫你處理了。
將高版本的js代碼轉換成低版本的js代碼。好比ie瀏覽器不兼容es6,須要使用babel把es6代碼把js轉換成低版本的js代碼。
安裝:npm install --save-dev babel-loader @babel/core
git
module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] }
babel-loader
並不會幫助你把es6語法轉換成低級的語法。它只是幫助打通webpack跟babel之間的聯繫。
轉換成es5的語法:
安裝:npm install @babel/preset-env --save-dev
@babel/preset-env
包含了es6轉換成es5的全部規則。es6
module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "presets": ["@babel/preset-env"] } } ] }
若是還須要降到更低版本就得使用babel-polyfill
安裝:npm install --save @babel/polyfill
頁面頂部引入import "@babel/polyfill";
就能夠將高級版本語法轉換成低級語法。可是直接import
會讓打包後的文件很是大。
這個時候就須要再配置webpack.config.js
useBuiltIns
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { // "presets": ["@babel/preset-env"] // 當你作babel-polyfill往瀏覽器填充的時候,根據業務代碼用到什麼加什麼,並不會所有寫入, // 數組中,後面的對象是對數組前面的babel作配置 "presets": [["@babel/preset-env", { useBuiltIns: 'usage' }]] } }
若是開發一個第三方庫,類庫。使用babel-polyfill
會注入到全局,污染到全局環境。
安裝:npm install --save-dev @babel/plugin-transform-runtime
安裝:npm install --save @babel/runtime
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "plugins": ["@babel/plugin-transform-runtime"] } }
當你要添加配置時
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "plugins": [["@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": false, "helpers": true, "regenerator": true, "useESModules": false }]] } }
若是你要將corejs賦值爲2
安裝:npm install --save @babel/runtime-corejs2
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "plugins": [["@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": 2, "helpers": true, "regenerator": true, "useESModules": false }]] } }
@babel/plugin-transform-runtime
不會污染到全局環境。
當babel配置很是多的時候,能夠將他們放到.babelrc
文件裏
在根目錄下建立.babelrc
文件
將options
裏的代碼放到這個文件中,以下:
{ "plugins": [["@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": 2, "helpers": true, "regenerator": true, "useESModules": false }]] }
安裝:npm install --save-dev @babel/preset-react
往剛剛的.babelrc
文件中添加配置
// presets對應一個數組,若是這個值須要作配置,那麼這個值在包裝進一個數組,放到第一項,第二項是個對象,用於描述該babel { "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage" }], "@babel/preset-react" ] }
注意:轉換是先下後上,就是使用preset-react轉換react代碼,再用preset-env將js代碼轉換爲es5代碼