還是以前一樣,有些概念面試可能會考,我都用*標記了出來,兩句話就總結清楚其餘的地方如果你想了解webpack,就仔細看看,雖然本教程不能讓你webpack玩的很6,但是懂操作流程夠了。面試你一般問你webpack的原理,Loader的原理,你有用那些優化措施
這篇文章共享之前我仍是要引薦下我自個的前端群:657137906,不論你是小白仍是大牛,小編我都挺期待,不定期共享乾貨,包含我自個整理的一份2017最新的前端材料和零根底入門教程,期待初學和進階中的小夥伴。
前端開發已經模塊化,它改進了代碼庫的封裝和結構。打包工具已經成為了一個項目必不可少的部分,
如今這兒有幾種可能的選擇,例如webpack,grunt,gulp等。
webpack因為他的功能和擴展性在過去的幾年中,受到非常大的歡迎。但是webpack的配置總是讓人覺得很困惑,
今天我們將從一個空的配置文件逐步完成一個完整的設置進行打包文件。
概念
不像大多數的模塊打包機,webpack是收把項目當作一個整體,通過一個給定的的主文件,webpack將從這個文件開始找到你的項目的所有依賴文件,使用loaders處理它們,最後打包成一個或多個瀏覽器可識別的js文件
install
首先添加我們即將使用的包:
npm install webpack webpack-dev-server --save-dev
webpack是我們需要的模塊打包機,webpack-dev-server用來創建本地服務器,監聽你的代碼修改,並自動刷新修改後的結果。這些是有關devServer的配置
contentBase, // 為文件提供本地服務器port, // 監聽端口,默認8080inline, // 設置為true,源文件發生改變自動刷新頁面historyApiFallback // 依賴HTML5 history API,如果設置為true,所有的頁面跳轉指向index.htmldevServer:{ contentBase: './src' // 本地服務器所加載的頁面所在的目錄 historyApiFallback: true, // 不跳轉 inline: true // 實時刷新}然後我們在根目錄下創建一個'webpack.config.js',在'package.json'添加兩個命令用於本地開發和生產發佈 "scripts": { "start": "webpack-dev-server", "build": "webpack" }
在使用webpack命令的時候,他將接受webpack的配置文件,除非我們使用其他的操作
entry
entry: 用來寫入口文件,它將是整個依賴關係的根
var baseConfig = { entry: './src/index.js' }
當我們需要多個入口文件的時候,可以把entry寫成一個對象
var baseConfig = { entry: { main: './src/index.js' } }
我建議使用後面一種方法,因為他的規模會隨你的項目增大而變得繁瑣
output
output: 即使入口文件有多個,但是隻有一個輸出配置
var path = require('path') var baseConfig = { entry: { main: './src/index.js' }, output: { filename: 'main.js', path: path.resolve('./build') } } module.exports = baseConfig
如果你定義的入口文件有多個,那麼我們需要使用佔位符來確保輸出文件的唯一性
output: { filename: '[name].js', path: path.resolve('./build') }
如今這麼少的配置,就能夠讓你運行一個服務器並在本地使用命令npm start或者npm run build來打包我們的代碼進行發佈
Loader
loader的作用:
1、實現對不同格式的文件的處理,比如說將scss轉換為css,或者typescript轉化為js
2、轉換這些文件,從而使其能夠被添加到依賴圖中
loader是webpack最重要的部分之一,通過使用不同的Loader,我們能夠調用外部的腳本或者工具,實現對不同格式文件的處理,loader需要在webpack.config.js裡邊單獨用module進行配置,配置如下:
test: 匹配所處理文件的擴展名的正則表達式(必須) loader: loader的名稱(必須) include/exclude: 手動添加處理的文件,屏蔽不需要處理的文件(可選) query: 為loaders提供額外的設置選項 ex: var baseConfig = { // ... module: { rules: [ { test: /*匹配文件後綴名的正則*/, use: [ loader: /*loader名字*/, query: /*額外配置*/ ] } ] } }
要是loader工作,我們需要一個正則表達式來標識我們要修改的文件,然後有一個數組表示
我們表示我們即將使用的Loader,當然我們需要的loader需要通過npm 進行安裝。例如我們需要解析less的文件,那麼webpack.config.js的配置如下:
var baseConfig = { entry: { main: './src/index.js' }, output: { filename: '[name].js', path: path.resolve('./build') }, devServer: { contentBase: './src', historyApiFallBack: true, inline: true }, module: { rules: [ { test: /\.less$/, use: [ {loader: 'style-loader'}, {loader: 'css-loader'}, {loader: 'less-loader'} ], exclude: /node_modules/ } ] } }
這裡介紹幾個常用的loader:
babel-loader: 讓下一代的js文件轉換成現代瀏覽器能夠支持的JS文件。
babel有些複雜,所以大多數都會新建一個.babelrc進行配置
css-loader,style-loader:兩個建議配合使用,用來解析css文件,能夠解釋@import,url()如果需要解析less就在後面加一個less-loader
file-loader: 生成的文件名就是文件內容的MD5哈希值並會保留所引用資源的原始擴展名
url-loader: 功能類似 file-loader,但是文件大小低於指定的限制時,可以返回一個DataURL事實上,在使用less,scss,stylus這些的時候,npm會提示你差什麼插件,差什麼,你就安上就行了
Plugins
plugins和loader很容易搞混,說都是外部引用有什麼區別呢? 事實上他們是兩個完全不同的東西。這麼說loaders負責的是處理源文件的如css、jsx,一次處理一個文件。而plugins並不是直接操作單個文件,它直接對整個構建過程起作用下面列舉了一些我們常用的plugins和他的用法
ExtractTextWebpackPlugin: 它會將入口中引用css文件,都打包都獨立的css文件中,而不是內嵌在js打包文件中。下面是他的應用
var ExtractTextPlugin = require('extract-text-webpack-plugin') var lessRules = { use: [ {loader: 'css-loader'}, {loader: 'less-loader'} ] } var baseConfig = { // ... module: { rules: [ // ... {test: /\.less$/, use: ExtractTextPlugin.extract(lessRules)} ] }, plugins: [ new ExtractTextPlugin('main.css') ] }
HtmlWebpackPlugin:
作用: 依據一個簡單的index.html模版,生成一個自動引用你打包後的js文件的新index.html
var HTMLWebpackPlugin = require('html-webpack-plugin') var baseConfig = { // ... plugins: [ new HTMLWebpackPlugin() ] }
HotModuleReplacementPlugin: 它允許你在修改組件代碼時,自動刷新實時預覽修改後的結果注意永遠不要在生產環境中使用HMR。這兒說一下一般情況分為開發環境,測試環境,生產環境。
用法如 new webpack.HotModuleReplacementPlugin()
webapck.config.js的全部內容 const webpack = require("webpack") const HtmlWebpackPlugin = require("html-webpack-plugin") var ExtractTextPlugin = require('extract-text-webpack-plugin') var lessRules = { use: [ {loader: 'css-loader'}, {loader: 'less-loader'} ] } module.exports = { entry: { main: './src/index.js' }, output: { filename: '[name].js', path: path.resolve('./build') }, devServer: { contentBase: '/src', historyApiFallback: true, inline: true, hot: true }, module: { rules: [ {test: /\.less$/, use: ExtractTextPlugin.extract(lessRules)} ] }, plugins: [ new ExtractTextPlugin('main.css') ] }
產品階段的構建
目前為止,在開發階段的東西我們已經基本完成了。但是在產品階段,還需要對資源進行別的
處理,例如壓縮,優化,緩存,分離css和js。首先我們來定義產品環境
var ENV = process.env.NODE_ENV var baseConfig = { // ... plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(ENV) }) ] }
然後還需要修改我們的script命令
"scripts": { "start": "NODE_ENV=development webpack-dev-server", "build": "NODE_ENV=production webpack" }
process.env.NODE_ENV 將被一個字符串替代,它運行壓縮器排除那些不可到達的開發代碼分支。
當你引入那些不會進行生產的代碼,下面這個代碼將非常有用。
if (process.env.NODE_ENV === 'development') { console.warn('這個警告會在生產階段消失') }
優化插件
下面介紹幾個插件用來優化代碼
OccurenceOrderPlugin: 為組件分配ID,通過這個插件webpack可以分析和優先考慮使用最多 的模塊,然後為他們分配最小的ID
UglifyJsPlugin: 壓縮代碼
下面是他們的使用方法
var baseConfig = {
// ...new webpack.optimize.OccurenceOrderPlugin()new webpack.optimize.UglifyJsPlugin()
}
然後在我們使用npm run build會發現代碼是壓縮的
總結
webpack的配置文件的複雜度,依賴於你項目的需要。小心的運用他們。因為隨著項目的增長,它們會變得很難馴服。內容有點多,事實上總結起來也不是特別多,也就Loader,plugins。其他的地方都比較簡單。這篇文章大概花了我三天的時間,網上看各種教程,然後看官網,真挺累的。這兒寫完我就去睡覺
最後在說幾句:
厲害程序員相對於普通程序員的優勢在於:
寫出的代碼更容易排錯,不是高手的代碼就不會錯,而是高手的代碼出了錯容易找。高手的代碼可讀性一定很好,模塊清晰,命名規範,格式工整,關鍵的地方有註釋,出了異常有log,自然容易排錯,即使交給別人去debug也是比較容易的。
今天這個圖片彈窗特效到這裡寫完了,學習web前端的可以加我的群,每天分享對應的學習資料:657137906,歡迎初學和進階中的小夥伴。多寫多練。