什麼是webpack 本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。
webpack 有哪些功能(代碼轉換 文件優化 代碼分割 模塊合併 自動刷新 代碼校驗 自動發佈)
首先學習webpack 須要有簡單的node 基礎 ,打開node 官方網站進行安裝node, http://nodejs.cn/ 下載最新版node包並進行安裝。css
安裝完畢在終端 快速建立node項目 執行命令npm init -y 生成packge.json
在當前目錄安裝本地webpack
終端執行命令:
npm i webpack webpack-cli -d
i表示install ,d表示當前是開發環境安裝完成會產生node_modules文件
webpack 能夠進行0配置 而且webpack是打包工具(默認是js模塊 經過入口進行打包輸出打包後js結果)。
建立src目錄 --> 建立index.js -> 輸出:console.log('hello webpack');
npx 語法進行把index.js 進行打包
終端執行命令:
npx webpack
咱們發現當前目錄生成了一個dist 目錄而且建立了一個main.js(如圖:)
執行順序:(默認找node_modules--->bin文件 --> webpack文件 )
這裏咱們明白了安裝webpack 必須安裝他的依賴 webpack-cli
webpack打包默認支持js模塊化 ->相似於common.jshtml
webpack:兩種默兩種模式若是沒有建立webpack.config.js 配置文件指定mode (production/development)生成模式或開發模式,打包運行會直接默認生產模式打包而且進行壓縮。
這裏說一下webpack配置文件的默認名稱有兩種 (webpack.config.js / webpackfile.js 通常狀況下咱們會選擇前一種)node
(1)建立webpack.config.js 配置文件 因爲webpack是node.js的框架因此配置文件中要採用node語法來進行編輯。webpack
const path = require("path"); //webpack內部方法path組件 module.exports = { mode: "development", //打包模式 development開發模式 entry: "./src/index.js", //入口文件指定 output: { //出口文件配置 配置出口打包路徑 filename: "build.js", //打包後的文件名稱 path: path.resolve(__dirname, "build") //resolve絕對路徑引入 } };
咱們分析一下build.js 打包出的結果,默認下是一個匿名函數 而且接收兩個參數 接收一個對象,Key : value (key:是當前模塊的路徑 value:是一個執行函數)
接收到modules 裏 先定義一個緩存對象 installedModules先定一個緩存目的是若是我當前模塊加載完成沒有必要再進行加載
webpack_require 實現了一個require方法由於瀏覽器沒法直接執行node的require方法 (詳解如圖)
執行__webpack_require__ 發現接收了一個入口模塊 git
終端運行: npx webpack , 發現咱們打包當前目錄產生了文件夾build目錄
分析了一下打包文件是否是感受webpack 源碼沒有想象的那麼難 繼續咱們webpack 的探索之旅。
如何更改webpack 配置文件名稱呢其實很簡單重命名webpack.config.js (webpack.test.js)
執行命令:
npx webpack --config webpack.test.js 發現能夠執行webpack打包。
這樣打包我發現命令很長因此咱們利用packge.json 來配置打包腳本在scripts-->添加build.es6
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --config webpack.config.js" }
終端運行 npm run build 發現執行打包結果同樣.
(2)webpack 其餘配 -->置插件的使用不會生成文件會生成內存中的打包
安裝webpck內置服務 webpack-dev-server 好處是
終端執行命令: npm i webpack-dev-server -d -save
安裝完成能夠執行 npx webpack-dev-server 按提示打開http://localhost:8080/
如何配置開發服務運行目錄能夠在配置文件中添加在webpack.config.js添加devServergithub
const path = require("path"); module.exports = { mode: "development", //打包模式 entry: "./src/index.js", //入口文件指定 output: { //出口文件配置 配置出口打包路徑 filename: "build.js", //打包的文件名稱 path: path.resolve(__dirname, "build") //resolve絕對路徑引入 }, devServer: { //開發服務器配置 contentBase: "./build", //指向打包目錄 port: 3000, //服務端口號 progress: true, //打包進度 open: true, //是否打開瀏覽器 compress: false //是否壓縮 } };
在packge.json中添加start 啓動服務腳本web
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --config webpack.config.js", "start":"webpack-dev-server" }
運行 npm run start 發現沒有自動建立index.html 不能直觀看到咱們代碼在瀏覽器的執行。
在src目錄下建立html模板 index.html 並安裝 html-webpack-plugin 插件
終端運行: npm i -d html-webpack-plugin
在webpack.config.js 下添加插件配置pluginsnpm
const path = require("path"); const HtmlWebPackPlugin = require("html-webpack-plugin"); module.exports = { mode: "development", //打包模式 entry: "./src/index.js", //入口文件指定 output: { //出口文件配置 配置出口打包路徑 filename: "build[hash:8].js", //打包的文件名稱 filename: "build[hash:8] 添加哈希值 path: path.resolve(__dirname, "build") //resolve絕對路徑引入 }, devServer: { //開發服務器配置 contentBase: "./build", //指向打包目錄 port: 3000, //服務端口號 progress: true, //打包進度 open: true, //是否打開瀏覽器 compress: false //是否壓縮 }, //插件 plugins: [ //數組形式 存放全部的webpack插件 new HtmlWebPackPlugin({ filename: "index.html", //生成打包文件名 template: "./src/index.html", //模板路徑 minify: { //生產模式能夠進行配置 removeAttributeQuotes: true, //刪除 html文件雙引號 collapseWhitespace: true //摺疊控行 }, hash:true, //添加哈希值 }) ] };
終端執行打包測試:npm run build (build目錄下生成了咱們想要生成的index.html文件)json
配置樣式須要一個合適loader,loader會將咱們的樣式文件解析成模塊(module)
終端:npm i -d --save css-loader style-loader
如何使用樣式loader進行配置呢? 咱們先在src下建index.css並給body賦予簡單樣式
在webpack.config.js 進行簡單配置
css-loader主要解析咱們樣式中@import語法,style-loader是吧css樣式插入head標籤中.
+ module: { //添加模塊模塊是對象 rules: [ //規則 css-loader主要解析咱們樣式中@import語法 { test: /\.css$/, use: ["style-loader", "css-loader"] //執行順序是重右向左執行 - >重下到上 } ] }
在index.js中引入樣式文件 import './index.css'
終端運行:npm run start 樣式生效了一樣咱們也有對應的less less-loader
終端:npm i -d --save less less-loader
在這裏說一下loader 的另外一種寫法對象寫法能夠給loader添加一些屬性options
+ module: { //添加模塊模塊是對象 rules: [ //規則 css-loader主要解析咱們樣式中@import語法 { test: /\.css$/, use: [ { loader: "style-loader", options: { insertAt: "top" //把標籤插入頂部 } }, "css-loader" ] //執行順序是重右向左執行 - >重下到上 }, { test: /\.less$/, use: [ { loader: "style-loader", options: { insertAt: "top" //把標籤插入頂部 } }, "css-loader", "less-loader" ] //執行順序是重右向左執行 - >重下到上 } ] }
css 樣式的抽離 安裝抽離插件 mini-css-extract-plugin npm i -d --save mini-css-extract-plugin
引入插件並在配置文件中進行配置
const path = require("path"); const HtmlWebPackPlugin = require("html-webpack-plugin"); const MinCssExtractPlugin = require("mini-css-extract-plugin"); //抽離css插件 module.exports = { mode: "development", //打包模式 entry: "./src/index.js", //入口文件指定 output: { //出口文件配置 配置出口打包路徑 filename: "[name][hash:8].js", //打包的文件名稱 filename: "build[hash:8] 添加哈希值 path: path.resolve(__dirname, "build") //resolve絕對路徑引入 }, devServer: { //開發服務器配置 contentBase: "./build", //指向打包目錄 port: 3000, //服務端口號 progress: true, //打包進度 open: true, //是否打開瀏覽器 compress: false //是否壓縮 }, //插件 plugins: [ //數組形式 存放全部的webpack插件 new HtmlWebPackPlugin({ filename: "index.html", //生成打包文件名 template: "./src/index.html", //模板路徑 minify: { removeAttributeQuotes: true, //刪除 html文件雙引號 collapseWhitespace: true //摺疊控行 }, hash: true //添加哈希值 }), new MinCssExtractPlugin({ filename: "mian.css" }) ], module: { //添加模塊模塊是對象 rules: [ //規則 css-loader主要解析咱們樣式中@import語法 { test: /\.css$/, use: [ MinCssExtractPlugin.loader, //建立link標籤放入到main.css裏 "css-loader" ] //執行順序是重右向左執行 - >重下到上 }, { test: /\.less$/, use: [ MinCssExtractPlugin.loader, //建立link標籤放入到main.css裏 "css-loader", "less-loader" ] //執行順序是重右向左執行 - >重下到上 } ] } }
添加樣式前綴 postcss-loader autoprefixer
npm i postcss-loader autoprefixer -d
module: { //添加模塊模塊是對象 rules: [ //規則 css-loader主要解析咱們樣式中@import語法 { test: /\.css$/, use: [ MinCssExtractPlugin.loader, //建立link標籤放入到main.css裏 "css-loader", "postcss-loader" ] //執行順序是重右向左執行 - >重下到上 }, { test: /\.less$/, use: [ MinCssExtractPlugin.loader, //建立link標籤放入到main.css裏 "css-loader", "postcss-loader", "less-loader" ] //執行順序是重右向左執行 - >重下到上 } ] }
module.exports = { plugins: [require("autoprefixer")] };
可是咱們發現問題使用mini-css-extract-plugin插件致使咱們css不會被壓縮。
npm 官網有給出To minify the output, use a plugin like optimize-css-assets-webpack-plugin. Setting optimization.minimizer overrides the defaults provided by webpack, so make sure to also specify a JS minimizer:參考連接
要使用optimize-css-assets-webpack-plugin 插件接下來咱們安裝配置一下.
npm i -d optimize-css-assets-webpack-plugin
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //壓縮js //配置文件中添加優化項 optimization: { minimizer: [new OptimizeCSSAssetsPlugin({})] }
使用optimize-css-assets-webpack-plugin咱們發現js右不會被壓縮 因此要使用uglifyjs-webpack-plugin --save-dev
$ npm install uglifyjs-webpack-plugin --save-dev
配置產考連接
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //壓縮js //配置文件中添加優化項 optimization: { minimizer: [new OptimizeCSSAssetsPlugin({}),new UglifyJsPlugin()] }
在index.js 裏寫點es6語法箭頭函數
let fn = () => { console.log("es6 webpack"); }; fn();
終端執行: npx webpack 查看打包文件
--咱們發現打包出來的仍然是es6語法這個時候咱們須要一個loader 進行轉換 babel-loader babel @babel/core
(babel/core是@babel-loader的核心組件轉化模塊@babel/preset-env) 參考連接
終端運行:npm i -d babel-loader babel @babel/core @babel/preset-env
在module添加配置
//在rules下添加配置 { test: /\.js$/, use: [ { loader: "babel-loader", options: { //轉化es5語法--presets預設 presets: ["@babel/preset-env"] } } ] },
終端運行:npm run build
發現能夠已經轉換es6語法 可是僅僅這樣不能轉換es6高階語法好比一些特殊的類函數
class Test { // new Test() a =1 實例上添加a屬性 這個語法屬於es7語法打包時發現並不能解析 a = 1; }
終端運行:npm run build 發現報錯提示安裝 @babel/plugin-proposal-class-properties
那咱們按照要求按照一下插件 npm i -d @babel/plugin-proposal-class-properties 並進行一次配置
//在rules下添加配置 { test: /\.js$/, use: [ { loader: "babel-loader", options: { //轉化es5語法--presets預設 presets: ["@babel/preset-env"], plugins: ["@babel/plugin-proposal-class-properties"] } } ] },
還有一種寫法 裝飾器@Log打包也是不被解析的 在js 添加
按照錯誤提示安裝decorators-legacy 參考連接 安裝官方給出配置添加
//在rules下添加配置 { test: /\.js$/, use: { { loader: "babel-loader", options: { //轉化es5語法--presets預設 presets: ["@babel/preset-env"], plugins: [ //這裏要注意添加順序 ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties", { loose: true }]] } } },
轉化完語法接下來看一下babel語法的校驗 @babel/plugin-transform-runtime @babel/runtime參考連接
{ test: /\.js$/, use: { loader: "babel-loader", options: { //轉化es5語法--presets預設 presets: ["@babel/preset-env"], plugins: [ ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties", { loose: true }], [ "@babel/plugin-transform-runtime", { absoluteRuntime: false, corejs: false, helpers: true, regenerator: true, useESModules: false } ] ] } }, include: path.resolve(__dirname, "src"), //只找__dirname - >src exclude: /node_modules/ //忽略node_modulse },
includes 實例方法不被解析 須要一個補丁模塊@babel/polyfill
npm install --save @babel/polyfill
Babel includes a polyfill that includes a custom regenerator runtime and core-js.
使用能夠直接在js 裏引入便可。
接下來看一下代碼校驗ESLint代碼校驗工具參考連接
終端安裝 npm i -d eslint eslint-loader
根據項目需求下載對應的eslintrc.json 下載連接
//代碼校驗eslint { test: /\.js$/, use: { loader: "eslint-loader", options: { enforce: "pre" //強制執行順序 } } },