詳解Web使用webpack構(gòu)建前端項(xiàng)目
好久沒寫技術(shù)博客了, 原因在于最近在學(xué)習(xí)前端方面的技術(shù), 熟悉我的同學(xué)都知道, 之前我有使用Vue搭建了一個(gè)個(gè)人簡(jiǎn)歷, 體驗(yàn)了一把最新的前端技術(shù), 但之前我們使用的是vue-cli腳手架工具, 對(duì)于如何自己實(shí)現(xiàn)前端構(gòu)建工具, 當(dāng)下最為流行的就是webpack和gulp了, 之前一篇我們講了gulp, 這一篇我們來(lái)好好討論webpack.
說(shuō)起webpack, 想必做前端的同學(xué)肯定不會(huì)陌生, 其實(shí)之前我們使用gulp構(gòu)建的時(shí)候, 也使用了webpack的打包技術(shù), 其實(shí)gulp和webpack并不是相互替代的關(guān)系, 而是相輔相成, 今天我們就來(lái)好好看看webpack的神奇之處吧.
我們學(xué)習(xí)一樣新技術(shù), 首先肯定是從他的官方文檔入手, 當(dāng)然我們要學(xué)習(xí)也是學(xué)最新版的.webpack的官方教程寫的非常好, 一步一步講的很到位, 各位同學(xué)可以直接閱讀官方文檔, 比起博客中的二手, 三手以及四手的資料, 官方文檔肯定是你更好的選擇.
這篇文章, 不是教你什么看這一篇就夠了之類的對(duì)于官方文檔拷貝的水文, 而是能讓你快速上手并且覺得所謂的webpack其實(shí)也就這么一回事, webpack你只要記住一個(gè)中心思想, 就和上面的圖示一樣, 將所有錯(cuò)綜復(fù)雜的文件邏輯打包壓縮成幾個(gè)靜態(tài)資源, 不多說(shuō)了, 我們還是看代碼來(lái)的實(shí)際.
webpack.config.js
對(duì)于一些拋棄jquery迎接react和vue的前端開發(fā)者來(lái)說(shuō), webpack雖然可能自己沒有寫過(guò), 但看總是看過(guò)的吧, 一般來(lái)說(shuō), 都會(huì)有一個(gè)webpack.config.js
的webpack配置文件.下面的代碼就是一個(gè)簡(jiǎn)單的webpack的配置, 麻雀雖小五臟俱全.
var debug = process.env.NODE_ENV !== "production"; //是否是測(cè)試環(huán)境 var webpack = require('webpack'); //導(dǎo)入webpack包 var path = require('path'); module.exports = { //導(dǎo)出 webpack固定寫法 context: path.join(__dirname), devtool: debug ? "inline-sourcemap" : null, //是否使用map工具, 用于瀏覽器debug entry: "./src/js/root.js", //打包的實(shí)體 module: { loaders: [ //加載的配置 { test: /\.js?$/, exclude: /(node_modules)/, loader: 'babel-loader', query: { presets: ['react', 'es2015'], //添加預(yù)處理器 plugins: ['react-html-attrs'], //添加組件的插件配置 } }, { test: /\.css$/, loader: 'style-loader!css-loader' }, { test: /\.less$/, loader: "style!css!less" } ] }, output: { //輸出的路徑及文件名 path: __dirname, filename: "./src/bundle.js" }, plugins: debug ? [] : [ //一些插件 new webpack.optimize.DedupePlugin(), new webpack.optimize.OccurenceOrderPlugin(), new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }), ], };
webpack主要包括entry, module, output, plugins
四大類, 官方文檔說(shuō)的已經(jīng)很清楚了, 想要進(jìn)一步的學(xué)習(xí),請(qǐng)翻閱官方文檔, 如果不想折騰直接拷貝上述代碼即可.
相較gulp, webpack在打包方面更為精簡(jiǎn), 這也是流行的原因吧, 但光看上面的文件, 的確也是簡(jiǎn)單, 但是還有進(jìn)一步改善的空間.
package.json
對(duì)于npm的介紹我就不多說(shuō)了, 我們直接來(lái)看文件.
{ "name": "webpack", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { //命令行工具 "test": "echo \"Error: no test specified\" && exit 1", "watch": "webpack --progress --watch", "start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { //開發(fā)環(huán)境依賴 "babel-loader": "^7.1.2", "clean-webpack-plugin": "^0.1.16", "css-loader": "^0.28.7", "csv-loader": "^2.1.1", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.30.1", "json-loader": "^0.5.7", "lodash": "^4.17.4", "style-loader": "^0.18.2", "uglifyjs-webpack-plugin": "^0.4.6", "webpack": "^3.6.0", "webpack-dev-middleware": "^1.12.0", "webpack-dev-server": "^2.8.2", "webpack-merge": "^4.1.0", "xml-loader": "^1.2.1" }, "dependencies": { //生產(chǎn)環(huán)境依賴 "babel-plugin-import": "^1.5.0", "babel-plugin-react-html-attrs": "^2.0.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babelify": "^7.3.0", "react": "^15.6.1", "react-dom": "^15.6.1", "react-mixin": "^4.0.0", "react-router": "^4.2.0" } }
命令行工具就是npm run build等于執(zhí)行了webpack --config webpack.prod.js, 而npm start 等于執(zhí)行了webpack-dev-server --open --config webpack.dev.js.簡(jiǎn)單易懂吧.
在項(xiàng)目依賴中, 哦們加了很多的插件和loader, 都是用來(lái)搭建webpack的, 官方文檔的教程中都會(huì)講到, 值得注意的就是webpack-merge這個(gè)包, 這個(gè)包可以讓我們生產(chǎn)環(huán)境和開發(fā)環(huán)境很好的隔離配置, 我們看看怎么做呢?
首先我們需要將之前的webpack.config.js分成三個(gè)文件 --- webpack.common.js, webpack.dev.js, webpack.prod.js.
webpack.common.js
這個(gè)是webpack的共同配置, 總體和之前看到的大同小異, 我們主要是導(dǎo)入了兩個(gè)插件, 一個(gè)是清除插件, 一個(gè)是創(chuàng)建html的插件.
const path = require('path'); const webpack = require('webpack'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({title: 'webpack'}), new webpack.HashedModuleIdsPlugin() ], output: { filename: '[name].[chunkhash].js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js?$/, exclude: /(node_modules)/, loader: 'babel-loader', query: { presets: [ 'react', 'es2015' ], plugins: ['react-html-attrs'] } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.(png|svg|jpg|gif)$/, use: ['file-loader'] }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use: ['file-loader'] }, { test: /\.(csv|tsv)$/, use: ['csv-loader'] }, { test: /\.xml$/, use: ['xml-loader'] } ] } };
rules
配置中我們也就是將一些可能用到的文件也配置到webpack中來(lái), babel-loader
這種如果要講還可以再開一篇, 其實(shí)就是個(gè)js的兼容性工具, 這樣理解就可以了.
webpack.dev.js
webpack開發(fā)環(huán)境的配置, 非常簡(jiǎn)單, 就是用了之前講的webpack-merge工具, 就和git一樣, 合并了webpack.common.js的配置外新加了可以進(jìn)行調(diào)試的inline-source-map工具, 以及熱更新的內(nèi)容索引.
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { devtool: 'inline-source-map', devServer: { contentBase: './dist' } });
webpack.prod.js
webpack生產(chǎn)環(huán)境的配置, 新加了一個(gè)壓縮插件以及環(huán)境配置的插件, 這里的開發(fā)工具和開發(fā)還款下的有所不同, 具體可直接看官方文檔.
const webpack = require('webpack'); const merge = require('webpack-merge'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const common = require('./webpack.common.js'); module.exports = merge(common, { devtool: 'source-map', plugins: [ new UglifyJSPlugin({sourceMap: true}), new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': JSON.stringify('production') } }) ] });
terminal
這樣我們就配置完成啦, 我們?cè)诮K端上輸入看下效果:
cd ../ && npm i
首先我們進(jìn)入到目錄下并進(jìn)行node包的安裝.
npm run build
MacBook-Pro-15:webpack zhushuangquan$ npm run build > webpack@1.0.0 build /Users/zhushuangquan/Documents/code/webpack > webpack --config webpack.prod.js clean-webpack-plugin: /Users/zhushuangquan/Documents/code/webpack/dist has been removed. Hash: 85b65f54ef1436b295a5 Version: webpack 3.6.0 Time: 1148ms Asset Size Chunks Chunk Names main.014ac9aa420264da48eb.js 671 bytes 0 [emitted] main main.014ac9aa420264da48eb.js.map 6.47 kB 0 [emitted] main index.html 197 bytes [emitted] [lVK7] ./src/index.js 184 bytes {0} [built] Child html-webpack-plugin for "index.html": 1 asset [3IRH] (webpack)/buildin/module.js 517 bytes {0} [built] [DuR2] (webpack)/buildin/global.js 509 bytes {0} [built] + 2 hidden modules
我們可以看到已經(jīng)打包好的文件:
main.014ac9aa420264da48eb.js
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n(n.s="lVK7")}({lVK7:function(e,n,t){"use strict";document.body.appendChild(function(){var e=document.createElement("div");return e.innerHTML="Hello webpack",e}())}}); //# sourceMappingURL=main.014ac9aa420264da48eb.js.map
我們可以看到在webpack的打包和壓縮下, 代碼已經(jīng)基本不可讀了. 所以我們需要加上之前的調(diào)試插件, 以便生產(chǎn)環(huán)境出現(xiàn)bug后的補(bǔ)救.
npm start
MacBook-Pro-15:webpack zhushuangquan$ npm start > webpack@1.0.0 start /Users/zhushuangquan/Documents/code/webpack > webpack-dev-server --open --config webpack.dev.js clean-webpack-plugin: /Users/zhushuangquan/Documents/code/webpack/dist has been removed. Project is running at http://localhost:8080/ webpack output is served from / Content not from webpack is served from ./dist webpack: wait until bundle finished: / Hash: 06f20ec519d58fbd5c28 Version: webpack 3.6.0 Time: 1460ms Asset Size Chunks Chunk Names main.5eb4d4e3f458c49658a2.js 852 kB 0 [emitted] [big] main index.html 197 bytes [emitted] [6Um2] (webpack)/node_modules/url/util.js 314 bytes {0} [built] [8o/D] (webpack)-dev-server/client/overlay.js 3.71 kB {0} [built] [HPf+] (webpack)/node_modules/url/url.js 23.3 kB {0} [built] [Lx3u] (webpack)/hot/log.js 1.04 kB {0} [optional] [built] [Sj28] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {0} [built] [TfA6] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built] [U2me] (webpack)/hot/emitter.js 77 bytes {0} [built] [V3KU] (webpack)-dev-server/client/socket.js 1.04 kB {0} [built] [cMmS] (webpack)-dev-server/client?http://localhost:8080 7.27 kB {0} [built] [gqsi] (webpack)-dev-server/node_modules/loglevel/lib/loglevel.js 7.74 kB {0} [built] [0] multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js 40 bytes {0} [built] [gt+Q] (webpack)-dev-server/node_modules/ansi-regex/index.js 135 bytes {0} [built] [lVK7] ./src/index.js 184 bytes {0} [built] [p7Vd] (webpack)/node_modules/punycode/punycode.js 14.7 kB {0} [built] [pEPF] (webpack)/node_modules/querystring-es3/index.js 127 bytes {0} [built] + 73 hidden modules Child html-webpack-plugin for "index.html": 1 asset [3IRH] (webpack)/buildin/module.js 517 bytes {0} [built] [DuR2] (webpack)/buildin/global.js 509 bytes {0} [built] [M4fF] ./node_modules/lodash/lodash.js 540 kB {0} [built] [a/t9] ./node_modules/html-webpack-plugin/lib/loader.js!./node_modules/html-webpack-plugin/default_index.ejs 538 bytes {0} [built] webpack: Compiled successfully.
我們可以看到打開了一個(gè)內(nèi)容為Hello webpack的網(wǎng)頁(yè)在8080端口, 當(dāng)我們修改了文件時(shí)候網(wǎng)頁(yè)會(huì)自動(dòng)刷新.
知識(shí)點(diǎn):
回到我們剛才的package.json的命令行配置來(lái)看.
"scripts": { //命令行工具 "test": "echo \"Error: no test specified\" && exit 1", "watch": "webpack --progress --watch", "start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js" },
- 上面的npm run build => webpack => webpack.prod.js, 就是執(zhí)行了生產(chǎn)環(huán)境的配置的打包命令.
- 上面的npm start => webpack-dev-server --open => webpack.dev.js, 就是執(zhí)行了開發(fā)環(huán)境配置的服務(wù)端命令.
- --config是用于執(zhí)行webpack配置文件的命令, 而默認(rèn)為webpack.config.js.
- webpack命令就是和之前的gulp的邏輯相似, 將entry實(shí)例復(fù)制到output路徑的邏輯. 當(dāng)然還伴隨著一系列的操作.
- webpack-dev-server --open命令是打開服務(wù)器并進(jìn)行熱加載的用途.
以上就是webpack的使用及邏輯, 并沒有想象中的復(fù)雜吧, 甚至可以說(shuō)是簡(jiǎn)單, 實(shí)測(cè)一天即可入門webpack.
由于webpack的配置是固定代碼, 我已經(jīng)打包上傳github, 需要的同學(xué)可以進(jìn)行下載.
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS實(shí)現(xiàn)的DIV塊來(lái)回滾動(dòng)效果示例
這篇文章主要介紹了JS實(shí)現(xiàn)的DIV塊來(lái)回滾動(dòng)效果,結(jié)合實(shí)例形式分析了JS通過(guò)時(shí)間函數(shù)定時(shí)觸發(fā)動(dòng)態(tài)改變頁(yè)面元素樣式的相關(guān)操作技巧,需要的朋友可以參考下2017-02-02JavaScript–Apple設(shè)備檢測(cè)示例代碼
JavaScript–Apple設(shè)備檢測(cè)示例代碼。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11微信小程序通過(guò)點(diǎn)擊事件跨頁(yè)面?zhèn)鲄⒓癲ata-方法傳參(data-)的示例詳解
在?vue?中,我們可以直接在點(diǎn)擊事件中放入傳遞的參數(shù)進(jìn)行傳參;然而微信小程序中并不適用這樣的寫法,但是微信小程序可以通過(guò)自定義屬性從而綁定參數(shù)使用,這篇文章主要介紹了微信小程序通過(guò)點(diǎn)擊事件跨頁(yè)面?zhèn)鲄⒁约癲ata-方法傳參(data-),需要的朋友可以參考下2023-12-12Javascript簡(jiǎn)寫條件語(yǔ)句(推薦)
下面小編就為大家?guī)?lái)一篇Javascript簡(jiǎn)寫條件語(yǔ)句(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06Javascript 中創(chuàng)建自定義對(duì)象的方法匯總
這篇文章主要匯總介紹了Javascript 中創(chuàng)建自定義對(duì)象的方法,需要的朋友可以參考下2014-12-12JavaScript中訪問節(jié)點(diǎn)對(duì)象的方法有哪些如何使用
js訪問節(jié)點(diǎn)對(duì)象的方法有很多,比如getElementById在本文將舉例為大家介紹下2013-09-09深入理解JavaScript系列(14) 作用域鏈介紹(Scope Chain)
在第12章關(guān)于變量對(duì)象的描述中,我們已經(jīng)知道一個(gè)執(zhí)行上下文 的數(shù)據(jù)(變量、函數(shù)聲明和函數(shù)的形參)作為屬性存儲(chǔ)在變量對(duì)象中2012-04-04JavaScript 嚴(yán)格模式(use strict)用法實(shí)例分析
這篇文章主要介紹了JavaScript 嚴(yán)格模式(use strict)用法,結(jié)合實(shí)例形式分析了JavaScript 嚴(yán)格模式的基本功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-03-03