基於webpack搭建前端工程解決方案探索

2021-02-26 SegmentFault

作者:dmyang

來源:SegmentFault 思否社區

本篇主要介紹webpack的基本原理以及基於webpack搭建純靜態頁面型前端項目工程化解決方案的思路。

關於前端工程


下面是百科關於「軟體工程」的名詞解釋:

軟體工程是一門研究用工程化方法構建和維護有效的、實用的和高質量的軟體的學科。

其中,工程化是方法,是將軟體研發的各個鏈路串接起來的工具。

對於軟體「工程化」,個人以為至少應當有如下特點:

有IDE的支持,負責初始化工程、工程結構組織、debug、編譯、打包等工作有固定或者約定的工程結構,規定軟體所依賴的不同類別的資源的存放路徑甚至代碼的寫法等軟體依賴的資源可能來自軟體開發者,也有可能是第三方,工程化需要集成對資源的獲取、打包、發布、版本管理等能力和其他系統的集成,如CI系統、運維系統、監控系統等

廣泛意義上講,前端也屬於軟體工程的範疇。

但前端沒有Eclipse、Visual Studio等為特定語言量身打造的IDE。因為前端不需要編譯,即改即生效,在開發和調試時足夠方便,只需要打開個瀏覽器即可完成,所以前端一般不會扯到「工程」這個概念。

在很長一段時間裡,前端很簡單,比如下面簡單的幾行代碼就能夠成一個可運行前端應用:

<!DOCTYPE html>
<html>
<head>
    <title>webapp</title>
    <link rel="stylesheet" href="app.css">
</head>
<body>
    <h1>app title</h1>
    <script src="app.js"></script>
</body>
</html>

但隨著webapp的複雜程度不斷在增加,前端也在變得很龐大和複雜,按照傳統的開發方式會讓前端失控:代碼龐大難以維護、性能優化難做、開發成本變高。

感謝Node.js,使得JavaScript這門前端的主力語言突破了瀏覽器環境的限制可以獨立運行在OS之上,這讓JavaScript擁有了文件IO、網絡IO的能力,前端可以根據需要任意定製研發輔助工具。

一時間出現了以Grunt、Gulp為代表的一批前端構建工具,「前端工程」這個概念逐漸被強調和重視。但是由於前端的複雜性和特殊性,前端工程化一直很難做,構建工具有太多局限性。

誠如 張雲龍@fouber 所言:

前端是一種特殊的GUI軟體,它有兩個特殊性:一是前端由三種程式語言組成,二是前端代碼在用戶端運行時增量安裝。

html、css和js的配合才能保證webapp的運行,增量安裝是按需加載的需要。開發完成後輸出三種以上不同格式的靜態資源,靜態資源之間有可能存在互相依賴關係,最終構成一個複雜的資源依賴樹(甚至網)。

所以,前端工程,最起碼需要解決以下問題:

資源管理,包括資源獲取、依賴處理、實時更新、按需加載、公共模塊管理等打通研發鏈路的各個環節,debug、mock、proxy、test、build、deploy等

其中,資源管理是前端最需要也是最難做的一個環節。

註:個人以為,與前端工程化對應的另一個重要的領域是前端組件化,前者屬於工具,解決研發效率問題,後者屬於前端生態,解決代碼復用的問題,本篇對於後者不做深入。

在此以開發一個多頁面型webapp為例,給出上面所提出的問題的解決方案。

前端開發環境搭建


主要目錄結構


- webapp/               # webapp根目錄
  - src/                # 開發目錄
    + css/              # css資源目錄
    + img/              # webapp圖片資源目錄
    - js/               # webapp js&jsx資源目錄
      - components/     # 標準組件存放目錄
          - foo/        # 組件foo
            + css/      # 組件foo的樣式
            + js/       # 組件foo的邏輯
            + tmpl/     # 組件foo的模板
            index.js    # 組件foo的入口
          + bar/        # 組件bar
      + lib/            # 第三方純js庫
      ...               # 根據項目需要任意添加的代碼目錄
    + tmpl/             # webapp前端模板資源目錄
    a.html              # webapp入口文件a
    b.html              # webapp入口文件b
  - assets/             # 編譯輸出目錄,即發布目錄
    + js/               # 編譯輸出的js目錄
    + img/              # 編譯輸出的圖片目錄
    + css/              # 編譯輸出的css目錄
    a.html              # 編譯輸出的入口a
    b.html              # 編譯處理後的入口b
  + mock/               # 假數據目錄
  app.js                # 本地server入口
  routes.js             # 本地路由配置
  webpack.config.js     # webpack配置文件
  gulpfile.js           # gulp任務配置
  package.json          # 項目配置
  README.md             # 項目說明

這是個經典的前端項目目錄結構,項目目結構在一定程度上約定了開發規範。業務開發的同學只需關注src目錄即可,開發時儘可能最小化模塊粒度,這是異步加載的需要。assets是整個工程的產出,無需關註裡邊的內容是什麼,至於怎麼打包和解決資源依賴的,往下看。

本地開發環境


我們使用開源web框架搭建一個webserver,便於本地開發和調試,以及靈活地處理前端路由,以koa為例,主要代碼如下:

// app.js
var http = require('http');
var koa = require('koa');
var serve = require('koa-static');

var app = koa();
var debug = process.env.NODE_ENV !== 'production';
// 開發環境和生產環境對應不同的目錄
var viewDir = debug ? 'src' : 'assets';

// 處理靜態資源和入口文件
app.use(serve(path.resolve(__dirname, viewDir), {
    maxage: 0
}));

app = http.createServer(app.callback());

app.listen(3005, '0.0.0.0', function() {
    console.log('app listen success.');
});

運行node app啟動本地server,瀏覽器輸入http://localhost:3005/a.html即可看到頁面內容,最基本的環境就算搭建完成。

如果只是處理靜態資源請求,可以有很多的替代方案,如Fiddler替換文件、本地起Nginx伺服器等等。搭建一個Web伺服器,個性化地定製開發環境用於提升開發效率,如處理動態請求、dnsproxy(多用於解決移動端配置host的問題)等,總之local webserver擁有無限的可能。

定製動態請求


我們的local server是localhost域,在ajax請求時為了突破前端同源策略的限制,本地server需支持代理其他域下的api的功能,即proxy。同時還要支持對未完成的api進行mock的功能。

// app.js
var router = require('koa-router')();
var routes = require('./routes');
routes(router, app);
app.use(router.routes());


// routes.js
var proxy = require('koa-proxy');
var list = require('./mock/list');
module.exports = function(router, app) {
    // mock api
    // 可以根據需要任意定製接口的返回
    router.get('/api/list', function*() {
        var query = this.query || {};
        var offset = query.offset || 0;
        var limit = query.limit || 10;
        var diff = limit - list.length;

        if(diff <= 0) {
            this.body = {code: 0, data: list.slice(0, limit)};
        } else {
            var arr = list.slice(0, list.length);
            var i = 0;

            while(diff--) arr.push(arr[i++]);

            this.body = {code: 0, data: arr};
        }
    });

    // proxy api
    router.get('/api/foo/bar', proxy({url: 'http://foo.bar.com'}));
}

webpack資源管理


資源的獲取


ECMAScript 6之前,前端的模塊化一直沒有統一的標準,僅前端包管理系統就有好幾個。所以任何一個庫實現的loader都不得不去兼容基於多種模塊化標準開發的模塊。

webpack同時提供了對CommonJS、AMD和ES6模塊化標準的支持,對於非前三種標準開發的模塊,webpack提供了shimming modules的功能。

受Node.js的影響,越來越多的前端開發者開始採用CommonJS作為模塊開發標準,npm已經逐漸成為前端模塊的託管平臺,這大大降低了前後端模塊復用的難度。

在webpack配置項裡,可以把node_modules路徑添加到resolve search root列表裡邊,這樣就可以直接load npm模塊了:

// webpack.config.js
resolve: {
    root: [process.cwd() + '/src', process.cwd() + '/node_modules'],
    alias: {},
    extensions: ['', '.js', '.css', '.scss', '.ejs', '.png', '.jpg']
},

$ npm install jquery react --save

// page-x.js
import $ from 'jquery';
import React from 'react';

資源引用


根據webpack的設計理念,所有資源都是「模塊」,webpack內部實現了一套資源加載機制,這與Requirejs、Sea.js、Browserify等實現有所不同,除了藉助插件體系加載不同類型的資源文件之外,webpack還對輸出結果提供了非常精細的控制能力,開發者只需要根據需要調整參數即可:

// webpack.config.js
// webpack loaders的配置示例
...
loaders: [
    {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: [
            'image?{bypassOnDebug: true, progressive:true, \
                optimizationLevel: 3, pngquant:{quality: "65-80"}}',
            'url?limit=10000&name=img/[hash:8].[name].[ext]',
        ]
    },
    {
        test: /\.(woff|eot|ttf)$/i,
        loader: 'url?limit=10000&name=fonts/[hash:8].[name].[ext]'
    },
    {test: /\.(tpl|ejs)$/, loader: 'ejs'},
    {test: /\.js$/, loader: 'jsx'},
    {test: /\.css$/, loader: 'style!css'},
    {test: /\.scss$/, loader: 'style!css!scss'},
]
...

簡單解釋下上面的代碼,test項表示匹配的資源類型,loader或loaders項表示用來加載這種類型的資源的loader,loader的使用可以參考using loaders,更多的loader可以參考list of loaders。

對於開發者來說,使用loader很簡單,最好先配置好特定類型的資源對應的loaders,在業務代碼直接使用webpack提供的require(source path)接口即可:

// a.js
// 加載css資源
require('../css/a.css');

// 加載其他js資源
var foo = require('./widgets/foo');
var bar = require('./widgets/bar');

// 加載圖片資源
var loadingImg = require('../img/loading.png');

var img = document.createElement('img');

img.src = loadingImg;

注意,require()還支持在資源path前面指定loader,即require(![loaders list]![source path])形式:

require("!style!css!less!bootstrap/less/bootstrap.less");
// 「bootstrap.less」這個資源會先被"less-loader"處理,
// 其結果又會被"css-loader"處理,接著是"style-loader"
// 可類比pipe操作

require()時指定的loader會覆蓋配置文件裡對應的loader配置項。

資源依賴處理


通過loader機制,可以不需要做額外的轉換即可加載瀏覽器不直接支持的資源類型,如.scss、.less、.json、.ejs等。

但是對於css、js和圖片,採用webpack加載和直接採用標籤引用加載,有何不同呢?

運行webpack的打包命令,可以得到a.js的輸出的結果:

webpackJsonp([0], {
    /***/0:
    /***/function(module, exports, __webpack_require__) {

        __webpack_require__(6);

        var foo = __webpack_require__(25);
        var bar = __webpack_require__(26);

        var loadingImg = __webpack_require__(24);
        var img = document.createElement('img');

        img.src = loadingImg;
    },

    /***/6:
    /***/function(module, exports, __webpack_require__) {
        ...
    },

    /***/7:
    /***/function(module, exports, __webpack_require__) {
        ...
    },

    /***/24:
    /***/function(module, exports) {
        ...
    },

    /***/25:
    /***/function(module, exports) {
        ...
    },

    /***/26:
    /***/function(module, exports) {
        ...
    }
});

從輸出結果可以看到,webpack內部實現了一個全局的webpackJsonp()用於加載處理後的資源,並且webpack把資源進行重新編號,每一個資源成為一個模塊,對應一個id,後邊是模塊的內部實現,而這些操作都是webpack內部處理的,使用者無需關心內部細節甚至輸出結果。

上面的輸出代碼,因篇幅限制刪除了其他模塊的內部實現細節,完整的輸出請看a.out.js,來看看圖片的輸出:

/***/24:
/***/function(module, exports) {

    module.exports = "data:image/png;base64,...";

    /***/
}

注意到圖片資源的loader配置:

{
    test: /\.(jpe?g|png|gif|svg)$/i,
    loaders: [
        'image?...',
        'url?limit=10000&name=img/[hash:8].[name].[ext]',
    ]
}

意思是,圖片資源在加載時先壓縮,然後當內容size小於~10KB時,會自動轉成base64的方式內嵌進去,這樣可以減少一個HTTP的請求。當圖片大於10KB時,則會在img/下生成壓縮後的圖片,命名是[hash:8].[name].[ext]的形式。hash:8的意思是取圖片內容hashsum值的前8位,這樣做能夠保證引用的是圖片資源的最新修改版本,保證瀏覽器端能夠即時更新。

對於css文件,默認情況下webpack會把css content內嵌到js裡邊,運行時會使用style標籤內聯。如果希望將css使用link標籤引入,可以使用ExtractTextPlugin插件進行提取。

資源的編譯輸出


webpack的三個概念:模塊(module)、入口文件(entry)、分塊(chunk)。

其中,module指各種資源文件,如js、css、圖片、svg、scss、less等等,一切資源皆被當做模塊。

webpack編譯輸出的文件包括以下2種:

entry:入口,可以是一個或者多個資源合併而成,由html通過script標籤引入chunk:被entry所依賴的額外的代碼塊,同樣可以包含一個或者多個文件

下面是一段entry和output項的配置示例:

entry: {
    a: './src/js/a.js'
},
output: {
    path: path.resolve(debug ? '__build' : './assets/'),
    filename: debug ? '[name].js' : 'js/[chunkhash:8].[name].min.js',
    chunkFilename: debug ? '[chunkhash:8].chunk.js' : 'js/[chunkhash:8].chunk.min.js',
    publicPath: debug ? '/__build/' : ''
}

其中entry項是入口文件路徑映射表,output項是對輸出文件路徑和名稱的配置,佔位符如[id]、[chunkhash]、[name]等分別代表編譯後的模塊id、chunk的hashnum值、chunk名等,可以任意組合決定最終輸出的資源格式。hashnum的做法,基本上弱化了版本號的概念,版本迭代的時候chunk是否更新只取決於chnuk的內容是否發生變化。

細心的同學可能會有疑問,entry表示入口文件,需要手動指定,那麼chunk到底是什麼,chunk是怎麼生成的?

在開發webapp時,總會有一些功能是使用過程中才會用到的,出於性能優化的需要,對於這部分資源我們希望做成異步加載,所以這部分的代碼一般不用打包到入口文件裡邊。

對於這一點,webpack提供了非常好的支持,即code splitting,即使用require.ensure()作為代碼分割的標識。

例如某個需求場景,根據url參數,加載不同的兩個UI組件,示例代碼如下:

var component = getUrlQuery('component');

if('dialog' === component) {
    require.ensure([], function(require) {
        var dialog = require('./components/dialog');
        // todo ...
    });
}

if('toast' === component) {
    require.ensure([], function(require) {
        var toast = require('./components/toast');
        // todo ...
    });
}

url分別輸入不同的參數後得到瀑布圖:

webpack將require.ensure()包裹的部分單獨打包了,即圖中看到的[hash].chunk.js,既解決了異步加載的問題,又保證了加載到的是最新的chunk的內容。

假設app還有一個入口頁面b.html,那麼就需要相應的再增加一個入口文件b.js,直接在entry項配置即可。多個入口文件之間可能公用一個模塊,可以使用CommonsChunkPlugin插件對指定的chunks進行公共模塊的提取,下面代碼示例演示提取所有入口文件公用的模塊,將其獨立打包:

var chunks = Object.keys(entries);

plugins: [
    new CommonsChunkPlugin({
        name: 'vendors', // 將公共模塊提取,生成名為`vendors`的chunk
        chunks: chunks,
        minChunks: chunks.length // 提取所有entry共同依賴的模塊
    })
],

資源的實時更新


引用模塊,webpack提供了require()API(也可以通過添加bable插件來支持ES6的import語法)。但是在開發階段不可能改一次編譯一次,webpack提供了強大的熱更新支持,即HMR(hot module replace)。

HMR簡單說就是webpack啟動一個本地webserver(webpack-dev-server),負責處理由webpack生成的靜態資源請求。注意webpack-dev-server是把所有資源存儲在內存的,所以你會發現在本地沒有生成對應的chunk訪問卻正常。

下面這張來自webpack官網的圖片,可以很清晰地說明module、entry、chunk三者的關係以及webpack如何實現熱更新的:

enter0表示入口文件,chunk1~4分別是提取公共模塊所生成的資源塊,當模塊4和9發生改變時,因為模塊4被打包在chunk1中,模塊9打包在chunk3中,所以HMR runtime會將變更部分同步到chunk1和chunk3中對應的模塊,從而達到hot replace。

webpack-dev-server的啟動很簡單,配置完成之後可以通過cli啟動,然後在頁面引入入口文件時添加webpack-dev-server的host即可將HMR集成到已有伺服器:

...
<body>
    ...
    <script src="http://localhost:3005/__build/vendors.js"></script>
    <script src="http://localhost:3005/__build/a.js"></script>
</body>
...

因為我們的local server就是基於Node.js的webserver,這裡可以更進一步,將webpack開發伺服器以中間件的形式集成到local webserver,不需要cli方式啟動(少開一個cmd tab):

// app.js
var webpackDevMiddleware = require('koa-webpack-dev-middleware');
var webpack = require('webpack');
var webpackConf = require('./webpack.config');

app.use(webpackDevMiddleware(webpack(webpackConf), {
    contentBase: webpackConf.output.path,
    publicPath: webpackConf.output.publicPath,
    hot: true,
    stats: webpackConf.devServer.stats
}));

啟動HMR之後,每次保存都會重新編譯生成新的chnuk,通過控制臺的log,可以很直觀地看到這一過程:


公用代碼的處理:封裝組件


webpack解決了資源依賴的問題,這使得封裝組件變得很容易,例如:

// js/components/component-x.js
require('./component-x.css');

// @see https://github.com/okonet/ejs-loader
var template = require('./component-x.ejs');
var str = template({foo: 'bar'});

function someMethod() {}

exports.someMethod = someMethod;

使用:

// js/a.js
import {someMethod} from "./components/component-x";
someMethod();

正如開頭所說,將三種語言、多種資源合併成js來管理,大大降低了維護成本。

對於新開發的組件或library,建議推送到npm倉庫進行共享。如果需要支持其他加載方式(如RequireJS或標籤直接引入),可以參考webpack提供的externals項。

資源路徑切換


由於入口文件是手動使用script引入的,在webpack編譯之後入口文件的名稱和路徑一般會改變,即開發環境和生產環境引用的路徑不同:

// 開發環境
// a.html
<script src="/__build/vendors.js"></script>
<script src="/__build/a.js"></script>

// 生產環境
// a.html
<script src="http://cdn.site.com/js/460de4b8.vendors.min.js"></script>
<script src="http://cdn.site.com/js/e7d20340.a.min.js"></script>

webpack提供了HtmlWebpackPlugin插件來解決這個問題,HtmlWebpackPlugin支持從模板生成html文件,生成的html裡邊可以正確解決js打包之後的路徑、文件名問題,配置示例:

// webpack.config.js
plugins: [
    new HtmlWebpackPlugin({
        template: './src/a.html',
        filename: 'a',
        inject: 'body',
        chunks: ['vendors', 'a']
    })
]

這裡資源根路徑的配置在output項:

// webpack.config.js
output: {
    ...
    publicPath: debug ? '/__build/' : 'http://cdn.site.com/'
}

其他入口html文件採用類似處理方式。

輔助工具集成

local server解決本地開發環境的問題,webpack解決開發和生產環境資源依賴管理的問題。在項目開發中,可能會有許多額外的任務需要完成,比如對於使用compass生成sprites的項目,因目前webpack還不直接支持sprites,所以還需要compass watch,再比如工程的遠程部署等,所以需要使用一些構建工具或者腳本的配合,打通研發的鏈路。

因為每個團隊在部署代碼、單元測試、自動化測試、發布等方面做法都不同,前端需要遵循公司的標準進行自動化的整合,這部分不深入了。

對比&綜述


前端工程化的建設,早期的做法是使用Grunt、Gulp等構建工具。但本質上它們只是一個任務調度器,將功能獨立的任務拆解出來,按需組合運行任務。如果要完成前端工程化,這兩者配置門檻很高,每一個任務都需要開發者自行使用插件解決,而且對於資源的依賴管理能力太弱。

在國內,百度出品的fis也是一種不錯的工程化工具的選擇,fis內部也解決了資源依賴管理的問題。因筆者沒有在項目中實踐過fis,所以不進行更多的評價。

webpack以一種非常優雅的方式解決了前端資源依賴管理的問題,它在內部已經集成了許多資源依賴處理的細節,但是對於使用者而言只需要做少量的配置,再結合構建工具,很容易搭建一套前端工程解決方案。

基於webpack的前端自動化工具,可以自由組合各種開源技術棧(Koa/Express/其他web框架、webpack、Sass/Less/Stylus、Gulp/Grunt等),沒有複雜的資源依賴配置,工程結構也相對簡單和靈活。

附上筆者根據本篇的理論所完成的一個前端自動化解決方案項目模板:
webpack-seed : https://github.com/chemdemo/webpack-seed

點擊左下角閱讀原文,到 SegmentFault 思否社區 和文章作者展開更多互動和交流。

相關焦點

  • 基於 webpack 的前後端分離開發環境實踐
    web應用的早已開始告別單幹模式,為了提升開發效率,前後端分離的需求越來越被重視,前端負責展現/交互邏輯,後端負責業務/數據接口,基本上也成為了我們日常項目分工中的標配,但是前後端分離一直以來都是一個工程概念,每個團隊在實現工程中都會基於自身的技術棧選擇和開發環境進行具體的實現,本文便根據自身團隊在webapck開發中搭建的前後端分離開發環境進行部分敘述。
  • 基於webpack打包多頁應用,對前端工程化的思考
    前言在Vue,React 風靡的時代,加上基於框架衍生出來的各種腳手架,不得不說,現在 前端工程化 程度不遜色於任何端的開發隨著各種腳手架集成度的不斷提高,現在幾乎零配置就可以開發整個項目,俗稱傻瓜式開發是我們的代碼變傻了嗎?不!!
  • 教程 | 教你搭建通用的WebVR工程
    本文旨在介紹如何搭建WebVR工程以支持多場景開發。
  • 前端單元測試之Karma環境搭建
    因此最近在研究前端自動化測試框架Karma,把個人的學習過程分享出來,希望對大家有幫助。什麼是Karma?Karma是由Google團隊開發的一套前端測試運行框架。它不同於測試框架(例如jasmine,mocha等),運行在這些測試框架之上。
  • Antd Pro Vue - 基於阿里 Ant Design 的免費開源中後臺前端/設計解決方案
    基於優雅漂亮的 ant design 開發的管理後臺,為數不多的好看 admin。關於 Antd Pro VueAntd Pro Vue 是一個企業級中後臺前端/設計解決方案。在本站建站之初就推薦過Ant Design,這是阿里出品的免費開源的 web前端 UI 組件庫以及一套設計方案,主要用於開發 PC 端企業中後臺管理系統。
  • VR進化論|教你搭建通用的WebVR工程
    本文旨在介紹如何搭建WebVR工程以支持多場景開發。首先,作為一個基本的前端工程來說,我們需要讓代碼「工程化」,不僅要提供編譯構建、壓縮打包功能,還要讓每個頁面模塊化; 延伸到WebVR工程,我們也需要考慮「多頁面」模塊化,即提供多個場景模塊化開發,因為一個完整的WebVR App不僅僅只有一個場景。
  • 使用vue+node搭建前端異常監控系統
    使用vue+node搭建前端異常監控系統使用vue+node搭建前端異常監控系統(一)-原理剖析您將Get的技能收集前端錯誤(原生、React、
  • 前端常見跨域解決方案(全)
    主域相同,子域不同                不允許http://domain.com/c.js http://www.domain1.com/a.jshttp://www.domain2.com/b.js        不同域名                         不允許跨域解決方案
  • TypeScript(二)使用Webpack搭建環境
    這個章節裡面,我們就來完成它們的搭建,後續就可以愉快的來寫TypeScript代碼了。」一. 環境搭建1.1.VSCode環境搭建學習或者使用TypeScript有很多編輯器可以供我們選擇,目前前端開發比較常用的是兩個:WebStorm:JetBrains  公司的產品,用法和PHPStorm、PyCharm、IDEA用法基本一致;VSCode:Microsoft 公司的產品,目前可以說已經成為最流行的前端工具,並且本身就是TypeScript編寫的;在之前的Flutter文章中我有對比過
  • 前端 Webpack 工程化的最佳實踐
    Gulp還可以配合上眾多個性化插件(如gulp-streamify),從而使得整個前端的準備工作鏈路,變得清晰易控,如刷新頁面、代碼的編譯和壓縮等等。自動化「流水線」工具取代了很多繁雜的手動工作,可以說,是具有跨時代意義的。
  • 搭建基於Vue的前端架構,總結15點經驗(條理清晰,內容詳實,系統全面,細節到位)
    建立腳手架搭建 NPM 私服。使用 Node 環境開發 CLI 工具,參考我自己寫過的一篇 -【 搭建自己的腳手架—「優雅」生成前端工程】。基於 @vue/cli 搭建基礎的模板(大家都比較了解,節省開發時間,遠勝於從零開始搭建)。
  • 如何搭建一個高可用的服務端渲染工程
    二、SPA時代後來,誕生了SPA(Single Page Application),解決了上面說的部分問題:後端不需要關心表現層的邏輯,只需要注重服務層和業務邏輯層就可以了,暴露出相應的接口供前端調用。這種模式也同時實現了前後端解耦。本地開發的時候,前端只需要啟動一個本地服務,如:dev-server就可以開始開發了。
  • 基於Vue的前端架構,我總結15點經驗
    建立腳手架搭建 NPM 私服。使用 Node 環境開發 CLI 工具,參考我自己寫過的一篇 -【 搭建自己的腳手架—「優雅」生成前端工程】。基於 @vue/cli 搭建基礎的模板(大家都比較了解,節省開發時間,遠勝於從零開始搭建)。
  • 還學不會webpack?看這篇!
    我也不例外,以至於很長一段時間對webpack都是一知半解的狀態。但是想要繼續做好前端,webpack 是必須得跨過的一道坎,其實掌握 webpack 並不難,只是我們沒有找到正確的方法。本文就是我自己在學習 webpack 時的一點心得體會,供大家參考。什麼是webpack?
  • 史上最全的前端資源大匯總
    Webpack和React小書-gitbookwebpackWebpack,101入門體驗webpack入門教程基於webpack搭建前端工程解決方案探索9.移動端 API99移動端知識集合移動端前端開發知識庫移動前端的一些坑和解決方法(外觀表現)【原】移動web資源整理zepto 1.0 中文手冊zepto 1.0 中文手冊zepto 1.1.2zepto 中文注釋jqmobile 手冊移動瀏覽器開發集合移動開發大雜燴
  • 【第1271期】Webpack4+ 多入口程序構建
    經過時間的積累,慢慢的就有了一套感覺上還比較適合的webpack前端構建規範。那這裡來說說,webpack4+構建上的一些事吧。多入口的意思大概就是,訪問不同頁面的時候,主要的前端JS功能文件是不同的。最好的對比和區別就是SPA單頁面應用,每個頁面引入的文件都是同一份JS文件。
  • Vue 3 和 Webpack 5 來了,手動搭建的知識該更新了
    面試下一家公司的面試官問你,是否手動搭建過 Vue 項目的時候,對配置一問三不知🤔️ 。本文著重為大家講解從 0 到 1 搭建 Vue 3.x 開發環境 的過程中遇到的疑問。這裡提前說明,本文側重新手向,只搭建了開發環境,主要是讓大家了解一個過程,是一篇入門級別的文章,大佬對自己夠自信的話,就看到這裡,就此作罷。
  • 前端 mock 完美解決方案實戰
    它有這些功能:Mock功能介紹市面上講前端mock怎麼做的文章很多,整體上閱讀下來的沒有一個真正站在前端角度上讓我覺得強大和易用的。配置解耦耦合情況什麼是前端配置解耦,首先讓我們看下平時配置耦合情況有哪些:webpack-dev後端測試環境變了需要改git跟蹤的代碼開發的時候想這個接口mock 需要改git跟蹤的代碼 mockUrl ,mock?
  • 前端mock完美解決方案實戰
    配置解耦耦合情況什麼是前端配置解耦,首先讓我們看下平時配置耦合情況有哪些:webpack-dev後端測試環境變了需要改git跟蹤的代碼開發的時候想這個接口mock 需要改git跟蹤的代碼 mockUrl ,mock
  • Webpack 原理剖析:ES Module與CMD區別是...
    ,webpack是最熱門的工具之一,無論你用啥框架,走的哪條前端路線,都得會webpack。而且在跳槽面試的時候,尤其前端高級崗位的面試,你會發現面試官特別喜歡問 webpack 相關的東西,而且大多是原理性問題,比如:談談AST語法樹?談談babel的作用?如何收集代碼依賴?