聊一聊前端工程化演進(jìn)的那些事
前端工程化的演進(jìn)不是獨(dú)立的,是和前端其他領(lǐng)域息息相關(guān),一起成長(zhǎng)起來(lái)的,下面將從幾個(gè)維度先介紹一下前端發(fā)展背景。
前端職業(yè)演進(jìn)

ES演進(jìn)

開發(fā)模式

前端工程化
石器時(shí)代(JSP/PHP/單文件模式)
對(duì)前端的需求較弱,頁(yè)面比較簡(jiǎn)單,開發(fā)過(guò)程中沒有太多輔助工具 ,須臾手動(dòng)預(yù)覽文件、刷新代碼,前端代碼「裝飾」在PHP等代碼中。
(時(shí)代過(guò)于久遠(yuǎn),這里貼一張圖給大家體驗(yàn)一下)

青銅時(shí)代(非JS技術(shù)棧的打包工具)
maven介紹
托管公司內(nèi)部的maven jar/aar包,為客戶端或其他java程序發(fā)布提供支持。Maven 是一個(gè)構(gòu)建自動(dòng)化工具,主要用于 Java 項(xiàng)目。Maven 還可用于構(gòu)建和管理用 C#、Ruby、Scala 和其他語(yǔ)言編寫的項(xiàng)目。Maven 項(xiàng)目由 Apache 軟件基金會(huì)托管,它以前是雅加達(dá)項(xiàng)目的一部分。

YUI Compressor
YUI Compressor是當(dāng)時(shí)業(yè)界巨頭yahoo提供的一個(gè)前端壓縮工具,除了Compressor,雅虎當(dāng)時(shí)還提供了很多前端相關(guān)的工具和組件庫(kù)。
https://yui.github.io/yuicompressor/
一個(gè)maven打包js的小例子
<plugins>
<plugin>
<!-- YUI Compressor Maven壓縮插件 -->
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.5.1</version>
<executions>
<execution>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 讀取js,css文件采用UTF-8編碼 -->
<encoding>UTF-8</encoding>
<!-- 不顯示js可能的錯(cuò)誤 -->
<jswarn>false</jswarn>
<!-- 若存在已壓縮的文件,會(huì)先對(duì)比源文件是否有改動(dòng) 有改動(dòng)便壓縮,無(wú)改動(dòng)就不壓縮 -->
<force>false</force>
<!-- 在指定的列號(hào)后插入新行 -->
<linebreakpos>-1</linebreakpos>
<!-- 壓縮之前先執(zhí)行聚合文件操作 -->
<preProcessAggregates>true</preProcessAggregates>
<!-- 壓縮后保存文件后綴 無(wú)后綴 -->
<nosuffix>true</nosuffix>
<!-- 源目錄,即需壓縮的根目錄 -->
<sourceDirectory>src/main/static</sourceDirectory>
<!-- 輸出目錄,即壓縮后的目錄-->
<outputDirectory>target/classes</outputDirectory>
<force>true</force>
<!-- 壓縮js和css文件 -->
<includes>
<include>**/*.js</include>
<include>**/*.css</include>
</includes>
<!-- 以下目錄和文件不會(huì)被壓縮 -->
<excludes>
<exclude>**/*.min.js</exclude>
<exclude>**/*.min.css</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
總結(jié)
前端代碼會(huì)作為后端工程的一部分,被maven類的工具統(tǒng)一管理,發(fā)布到對(duì)應(yīng)的后端工程中
打包過(guò)程中js、css只能做簡(jiǎn)單的打包壓縮,無(wú)法做進(jìn)一步的管理。
白銀時(shí)代(JS技術(shù)棧打包工具)
通過(guò)編寫bash或nodejs編寫任務(wù)腳本,實(shí)現(xiàn)命令式的熱更新(HMR)和自動(dòng)打包,代表:Grunt、Gulp;
Grunt介紹
參考官網(wǎng):https://www.gruntjs.net/getting-started
一個(gè)Grunt打包的小例子
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON( package.json ),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today( yyyy-mm-dd ) %> */\n',
},
build: {
src: build/index.js ,
dest: build/<%= pkg.name %>.min.js ,
},
},
concat: {
build/index.js : [ src/foo.js , src/bar.js ],
},
});
// 加載包含 uglify 任務(wù)的插件。
grunt.loadNpmTasks( grunt-contrib-uglify );
// 加載包含 concat 任務(wù)的插件。
grunt.loadNpmTasks( grunt-contrib-concat );
// 默認(rèn)被執(zhí)行的任務(wù)列表。
grunt.registerTask( default , [ concat , uglify ]);
};
總結(jié)
JS技術(shù)棧的打包工具,前端可以基于node實(shí)現(xiàn)自己的打包工具,功能點(diǎn)和非js技術(shù)棧類似。
黃金時(shí)代(Bundle)
基于Bundle的概念,借用babel的能力,讓js文件按模塊的方式進(jìn)行打包,實(shí)現(xiàn)了HMR、以及各類處理器,讓前端的工程化脫離了簡(jiǎn)單的壓縮合并,轉(zhuǎn)入了更加豐富的黃金時(shí)間,代表:Webpack、Rollup;
一個(gè)webpack的小例子
var webpack = require('webpack');var path = require('path');var HtmlWebpackPlugin = require('html-webpack-plugin')var CleanWebpackPlugin = require('clean-webpack-plugin')var ExtractTextPlugin = require('extract-text-webpack-plugin')var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')const VENOR = [ faker ,
lodash ,
react ,
react-dom ,
react-input-range ,
react-redux ,
redux ,
redux-form ,
redux-thunk ,
react-router ]module.exports = {
entry: {
bundle: './src/index.js',
vendor: VENOR
},
// 如果想修改 webpack-dev-server 配置,在這個(gè)對(duì)象里面修改
devServer: {
port: 8081
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [{
test: /.js$/,
use: 'babel-loader'
},
{
test: /.(png|jpe?g|gif|svg)(?.*)?$/,
use: [{
loader: 'url-loader',
options: {
limit: 10000,
name: 'images/[name].[hash:7].[ext]'
}
}]
},
{
test: /.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
// 這邊其實(shí)還可以使用 postcss 先處理下 CSS 代碼
loader: 'css-loader'
}]
})
},
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor', 'manifest'],
minChunks: Infinity
}),
new CleanWebpackPlugin(['dist/*.js'], {
verbose: true,
dry: false
}),
new HtmlWebpackPlugin({
template: 'index.html'
}),
// 生成全局變量
new webpack.DefinePlugin({
process.env.NODE_ENV : JSON.stringify( process.env.NODE_ENV )
}),
// 分離 CSS 代碼
new ExtractTextPlugin( css/[name].[contenthash].css ),
// 壓縮提取出的 CSS,并解決ExtractTextPlugin分離出的 JS 重復(fù)問(wèn)題
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
}),
// 壓縮 JS 代碼
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]};
總結(jié)
正如webpack官網(wǎng)的banner圖描述,這個(gè)節(jié)點(diǎn)前端構(gòu)建脫離了簡(jiǎn)單的文件拼接壓縮,真正觸摸到了js間的關(guān)聯(lián),提供了更科學(xué)的工程化方案。

后黃金時(shí)代(Bundleless)
在Bundle的基礎(chǔ)上,結(jié)合瀏覽器解析原生ESM模塊的特性,實(shí)現(xiàn)Bundleless的開發(fā)預(yù)覽及熱更新(HMR),直接不打包發(fā)布或采用webpack等集成式工具兼容打包,代表:esbuild、snowpack。
snowpack介紹
官網(wǎng)介紹(from https://www.snowpack.dev/):
Snowpack is a lightning-fast frontend build tool, designed for the modern web. It is an alternative to heavier, more complex bundlers like webpack or Parcel in your development workflow. Snowpack leverages JavaScript's native module system (known as ESM) to avoid unnecessary work and stay fast no matter how big your project grows.
一個(gè)snowpack的小例子
/** @type {import( snowpack ).SnowpackUserConfig } */
export default {
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
},
plugins: [
'@snowpack/plugin-react-refresh',
'@snowpack/plugin-dotenv',
[
'@snowpack/plugin-typescript',
{
/* Yarn PnP workaround: see https://www.npmjs.com/package/@snowpack/plugin-typescript */
...(process.versions.pnp ? { tsc: 'yarn pnpify tsc' } : {}),
},
],
],
routes: [
/* Enable an SPA Fallback in development: */
// { match : routes , src : .* , dest : /index.html },
],
optimize: {
/* Example: Bundle your final build: */
// bundle : true,
},
packageOptions: {
/* ... */
},
devOptions: {
/* ... */
},
buildOptions: {
/* ... */
},
};
總結(jié)
思路上和webpack接近,解決了很多webpack的痛點(diǎn),但是概念是沒有g(shù)runt->webpack那么突破,所以定義為后黃金時(shí)代。
未來(lái)
前端工程化的未來(lái)有很多方向,有致力于提供全新工程化體系的Modern.js(https://modernjs.dev/),也有從效率出發(fā),希望實(shí)現(xiàn)更自動(dòng)、更智能的流水線方向的,不過(guò)結(jié)合其他語(yǔ)言的工程化進(jìn)程,如 Java,工程化的演進(jìn)可能還需要依賴整個(gè)生態(tài)的演進(jìn)才能有更革命性的進(jìn)展。
以上就是本期分享了。
最后,歡迎加入 魚皮的編程知識(shí)星球(點(diǎn)擊了解詳情),和大家一起交流學(xué)習(xí)編程,向魚皮和大廠同學(xué) 1 對(duì) 1 提問(wèn)、幫你制定學(xué)習(xí)計(jì)劃不迷茫、跟著魚皮直播做項(xiàng)目(往期項(xiàng)目可無(wú)限回看)、領(lǐng)取魚皮原創(chuàng)編程學(xué)習(xí)/求職資料等。最近秋招開始了,星球內(nèi)也會(huì)幫大家規(guī)劃求職進(jìn)度、完善簡(jiǎn)歷和項(xiàng)目。

往期推薦
