webpack是一個現代JavaScript應用程式的靜態模塊打包器,借用官網的一張圖,它能夠將一些預處理語言,js的最新語法轉換成瀏覽器識別的內容。現在一般的前端框架都有比較成熟的腳手架,大多數對webpack都有個較好的集成,我們只需要敲一些簡單的命令就能生成一個通用的項目模板,比較便捷,但是要 ...
webpack是一個現代JavaScript應用程式的靜態模塊打包器,借用官網的一張圖,它能夠將一些預處理語言,js的最新語法轉換成瀏覽器識別的內容。現在一般的前端框架都有比較成熟的腳手架,大多數對webpack都有個較好的集成,我們只需要敲一些簡單的命令就能生成一個通用的項目模板,比較便捷,但是要知其然知其所以然,所以今天就嘗試著從零開始搭建一個前端開發環境。
項目源碼:
https://github.com/gerryli0214/webpack-demo
webpack的四個核心概念:
1、入口(entry)
2、輸出(output)
3、loader
4、插件(plugins)
首先,我們執行下npm init;初始化一個node工程,填寫項目的信息,整個項目的目錄結構如下:
全部安裝webpack-cli:
npm install webpack-cli -g
安裝項目webpack依賴:
npm install webpack webpack-cli -D
新建一個webpack.config.js,這個是webpack預設配置文件,在裡面我們可以配置打包信息,初始化文件為:
const config = {};
module.exports = config;
入口(entry):
項目的入口文件,可以配置單個/多個,為入口文件的相對路徑,type:string/object;我們項目入口文件為index.js。
const config = { entry: './src/index.js' } module.exports = config;
輸出(output):
打包後的文件路徑和配置信息,path為打包文件路徑,filename為輸出文件名稱,name為原始文件名稱,hash為打包後的hash地址:
output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[hash].min.js' }
loader:
loader能夠處理非JavaScript文件,webpack預設只能處理JavaScript文件。在使用loader時,首先要安裝下指定loader的依賴,此部分的配置規則與之前版本有所差異,具體配置如下:
npm install babel-loader css-loader -D
module: { rules: [{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.js/, exclude: /node_modules/, //過濾node_modules文件夾 use: [{ loader: 'babel-loader' }] } ] }
插件(plugins):
插件是webpack最為強大的功能之一,利用插件,我們可以進行代碼的混淆、壓縮、重新定義項目環境變數等。插件分為webpack內置插件和第三方插件,第三方插件在使用時首先要安裝依賴和導入依賴模塊。詳細的使用方法可以參考npm。下麵羅列了幾個項目中常用的插件:
html-webpack-plugin:
主要作用:
1、為html文件中引入的外部資源如script
、link
動態添加每次compile後的hash,防止引用緩存的外部文件問題
2、可以生成創建html入口文件,比如單頁面可以生成一個html文件入口,配置多個就可以打包成多頁面
extract-text-webpack-plugin:
主要作用:分離打包的css文件
uglifyjs-webpack-plugin:
主要作用:混淆js代碼
webpack-bundle-analyzer:
主要作用:生成打包文件報告,可以看到各個模塊打包後文件大小信息
clean-webpack-plugin:
主要作用:每次打包之前清除dist文件夾
配置信息如下:
1 const path = require('path'); 2 const webpack = require('webpack'); 3 const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 6 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 7 const CleanWebpackPlugin = require('clean-webpack-plugin'); 8 9 const config = { 10 entry: './src/index.js', 11 output: { 12 path: path.resolve(__dirname, 'dist'), 13 filename: '[name].[hash].min.js' 14 }, 15 module: { 16 rules: [{ 17 test: /\.css$/, 18 use: ExtractTextPlugin.extract({ 19 fallback: 'style-loader', 20 use: 'css-loader' 21 }) 22 }, 23 { 24 test: /\.js/, 25 exclude: /node_modules/, //過濾node_modules文件夾 26 use: [{ 27 loader: 'babel-loader' 28 }] 29 } 30 ] 31 }, 32 optimization: { 33 splitChunks: { 34 name: "vendor", 35 filename: 'vendor-[hash].min.js' 36 }, 37 minimizer: [new UglifyJsPlugin()] 38 }, 39 plugins: [ 40 new HtmlWebpackPlugin({ template: './src/index.html' }), 41 new ExtractTextPlugin({ 42 filename: 'build.min.css', 43 allChunks: true, 44 }), 45 new webpack.BannerPlugin({ 46 banner: `構建時間:${new Date().getFullYear()}-${new Date().getMonth()+1}-${new Date().getDate()}` 47 }), 48 new CleanWebpackPlugin(), 49 // new webpack.EnvironmentPlugin({ NODE_ENV: 'production' }), 50 new BundleAnalyzerPlugin() 51 ] 52 }; 53 54 module.exports = config;
以上為打包的基礎配置信息,在我們實際開發中,經常會用到前端開發服務,模塊熱更新以及前端的跨域請求代理,webpack中提供了webpack-dev-server來滿足我們的需求,在使用之前先安裝下webpack-dev-server的依賴:
npm install webpack-dev-server -D
具體文件配置如下:
devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, host: '0.0.0.0', port: 9000, hot: true, //是否熱更新 proxy: { //代理 '/api': 'http://localhost:3000' } }
package.json中啟動命令配置如下:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --mode development", "build": "webpack --mode production" }
執行npm run start,執行結果如下:
這樣開發環境我們的主要配置就完成了,但是當我們用uglifyjs壓縮es6代碼時,會發現會報錯,因為uglifyjs不能壓縮es6的代碼,此時我們需要手動配置下babel,具體步驟如下:
1、安裝項目依賴
npm install @babel/core @babel/preset-env -D
2、新建在項目根目錄下.babelrc文件,填入以下配置信息
{ "presets":["@babel/preset-env"] }
執行npm run build,壓縮項目代碼,結果如下:
全部代碼:
const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const CleanWebpackPlugin = require('clean-webpack-plugin'); const config = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[hash].min.js' }, module: { rules: [{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.js/, exclude: /node_modules/, //過濾node_modules文件夾 use: [{ loader: 'babel-loader' }] } ] }, optimization: { splitChunks: { name: "vendor", filename: 'vendor-[hash].min.js' }, minimizer: [new UglifyJsPlugin()] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }), new ExtractTextPlugin({ filename: 'build.min.css', allChunks: true, }), new webpack.BannerPlugin({ banner: `構建時間:${new Date().getFullYear()}-${new Date().getMonth()+1}-${new Date().getDate()}` }), new CleanWebpackPlugin(), // new webpack.EnvironmentPlugin({ NODE_ENV: 'production' }), new BundleAnalyzerPlugin() ], devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, host: '0.0.0.0', port: 9000, hot: true, //是否熱更新 proxy: { //代理 '/api': 'http://localhost:3000' } }, devtool: 'source-map' }; module.exports = config;
參考資料:
webpack中文網:https://www.webpackjs.com
webpack內置插件列表:https://www.webpackjs.com/plugins/
第三方插件可自行搜索npm:https://www.npmjs.com/
項目源碼:
https://github.com/gerryli0214/webpack-demo
文筆比較粗糙,如有問題,煩請指出,謝謝!