摘要:前言微前端理論篇上一篇介紹了微前端的理念,本片將開(kāi)始介紹項(xiàng)目。先實(shí)現(xiàn)公共依賴的引入吧。在上一步我們沒(méi)有引入的依賴包,是因?yàn)榈囊蕾嚢亲鳛楣惨蕾噷?dǎo)入的。里面全是我的公共依賴文件在下新建文件夾,新建文件,作為我們整個(gè)項(xiàng)目的頁(yè)面文件。
前言
微前端 —— 理論篇
上一篇介紹了微前端的理念,本片將開(kāi)始介紹portal項(xiàng)目。
????????portal項(xiàng)目包括兩個(gè)功能:
????????1. 路由分發(fā)與應(yīng)用加載;
????????2. 抽離公共依賴;
目錄結(jié)構(gòu)如下:
新建一個(gè)文件夾,命名隨便,我的是portal
????????執(zhí)行npm init -y初始化package.json
????????現(xiàn)在我們要做什么呢?肯定是先引入依賴包啊
????????webpack打包相關(guān)和babel和簡(jiǎn)單幾個(gè)需要的loader就行了
????????npm i webpack webpack-cli webpack-dev-server style-loader css-loader copy-webpack-plugin clean-webpack-plugin babel-loader babel-core @babel/preset-env @babel/plugin-syntax-dynamic-import @babel/core -D
????????由于我們還需要同時(shí)運(yùn)行公共依賴引入和應(yīng)用加載兩個(gè)服務(wù),所以再 npm i concurrently -D
在引入所需的依賴之后,開(kāi)始實(shí)現(xiàn)相關(guān)功能。先實(shí)現(xiàn)公共依賴的引入吧。在上一步我們沒(méi)有引入single-spa的依賴包,是因?yàn)閟ingle-spa的依賴包是作為公共依賴導(dǎo)入的。
????????先創(chuàng)建一個(gè)公共依賴的文件夾,這個(gè)文件夾在任何地方都可以,因?yàn)槲覀兪峭ㄟ^(guò)遠(yuǎn)程鏈接引入的,要是你認(rèn)為的single-spa.js文件可以通過(guò)遠(yuǎn)程cdn或者其他鏈接取到,可以跳過(guò)這一步了,下面是我創(chuàng)建的公共依賴庫(kù)文件夾。
????????里面全是我的公共依賴文件
????????
????????在portal下新建src文件夾,新建文件index.html,作為我們整個(gè)項(xiàng)目的頁(yè)面文件。代碼如下
// 此處為從遠(yuǎn)程導(dǎo)入各個(gè)項(xiàng)目的js文件 // (react、vue項(xiàng)目打包和運(yùn)行都會(huì)產(chǎn)生一個(gè)js文件,此文件就是動(dòng)態(tài)渲染頁(yè)面用的) // config.js是portal項(xiàng)目產(chǎn)生的,用來(lái)進(jìn)行路由分發(fā)與組件狀態(tài)管理等
????????接下來(lái)實(shí)現(xiàn)common-deps.js,將我們所有的公共依賴文件統(tǒng)一引入,并命名
window.SystemJS = window.System function insertNewImportMap(newMapJSON) { const newScript = document.createElement("script") newScript.type = "systemjs-importmap" newScript.text = JSON.stringify(newMapJSON) const allMaps = document.querySelectorAll("script[type="systemjs-importmap"]") allMaps[allMaps.length - 1].insertAdjacentElement( "afterEnd", newScript ) } const devDependencies = { imports: { react: "http://localhost:8000/react.development.js", "react-dom": "http://localhost:8000/react-dom.development.js", "react-dom/server": "http://localhost:8000/react-dom-server.browser.development.js", "single-spa": "http://localhost:8000/single-spa.min.js", lodash: "http://localhost:8000/lodash.js", rxjs: "http://localhost:8000/rxjs.umd.js", } } const prodDependencies = { imports: { react: "http://localhost:8000/react.production.min.js", "react-dom": "http://localhost:8000/react-dom.production.min.js", "react-dom/server": "http://localhost:8000/react-dom-server.browser.production.min.js", "single-spa": "http://localhost:8000/single-spa.min.js", lodash: "http://localhost:8000/lodash.min.js", rxjs: "http://localhost:8000/rxjs.umd.min.js", } } const devMode = true // you will need to figure out a way to use a set of production dependencies instead if (devMode) { insertNewImportMap(devDependencies) } else { insertNewImportMap(prodDependencies) }
????????公共依賴的抽取代碼已經(jīng)實(shí)現(xiàn)了,下面就配置webpack,將這些依賴進(jìn)行打包,在項(xiàng)目根目錄創(chuàng)建 webpack.common-deps.config.js、webpack.common-deps.config.dev.js
????????webpack.common-deps.config.js
const path = require("path") const CleanWebpackPlugin = require("clean-webpack-plugin") const CopyWebpackPlugin = require("copy-webpack-plugin"); module.exports = { entry: "./src/common-deps.js", output: { filename: "common-deps.js", path: path.resolve(__dirname, "build/common-deps"), chunkFilename: "[name].js", }, mode: "production", node: { fs: "empty", }, resolve: { modules: [ __dirname, "node_modules", ], }, devtool: "sourcemap", plugins: [ new CleanWebpackPlugin(["build/common-deps/"]), CopyWebpackPlugin([ {from: path.resolve(__dirname, "src/common-deps.js")} ]), ], module: { rules: [ {parser: {System: false}}, { test: /.js$/, exclude: /(node_modules|bower_components)/, use: { loader: "babel-loader", } } ] } }
????????webpack.common-deps.config.dev.js
/* eslint-env node */ const config = require("./webpack.common-deps.config.js"); const webpack = require("webpack"); config.plugins.push(new webpack.NamedModulesPlugin()); config.plugins.push(new webpack.HotModuleReplacementPlugin()); config.devServer = { headers: { "Access-Control-Allow-Origin": "*", }, } config.mode = "development" module.exports = config;
????????上面配置dev-server跨域,很重要?。?!否則會(huì)因?yàn)闊o(wú)法跨域,訪問(wèn)不到j(luò)s文件
????????最后在package.json的scripts中添加命令
"scripts": { "test": "echo "Error: no test specified" && exit 1", "start:common-deps": "webpack-dev-server --config ./webpack.common-deps.config.dev.js --port 8234", "build:common-deps": "webpack --config ./webpack.common-deps.config.js -p" },
????????至此,公共依賴的抽取已經(jīng)完成,執(zhí)行npm run start:common-deps,公共依賴就被打包到了portal項(xiàng)目下的build/common-deps/目錄,通過(guò)import也可以正常導(dǎo)入使用(歸功于system)
公共依賴抽取實(shí)現(xiàn)、配置完畢之后,開(kāi)始利用single-spa構(gòu)建我們的路由分發(fā)系統(tǒng)
????????在src中創(chuàng)建文件activityFns.js,實(shí)現(xiàn)路由的正確匹配,內(nèi)容如下:
export function prefix(location, ...prefixes) { return prefixes.some( prefix => ( location.href.indexOf(`${location.origin}/${prefix}`) !== -1 ) ) } // return true 則加載 false則不加載 // 這里的menu是菜單,按理應(yīng)該一直加載出來(lái)的,因此return true export function menu(location) { return true } export function project1(location) { return prefix(location, "", "page1", "page2") } export function project2(location) { return prefix(location, "page3", "page4") }
????????在src中創(chuàng)建文件config.js,通過(guò)single-spa實(shí)現(xiàn)路由的注冊(cè)
import * as isActive from "./activityFns.js" import * as singleSpa from "single-spa" singleSpa.registerApplication("menu", () => SystemJS.import("@portal/menu"), isActive.menu) singleSpa.registerApplication("project1", () => SystemJS.import("@portal/project1"), isActive.project1) singleSpa.registerApplication("project2", () => SystemJS.import("@portal/project2"), isActive.project2) singleSpa.start()
????????配置webpack打包,在項(xiàng)目根目錄創(chuàng)建文件webpack.config.config.js,內(nèi)容如下:
/* eslint-env node */ const webpack = require("webpack") const path = require("path"); const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); module.exports = { entry: "./src/config.js", output: { filename: "config.js", library: "config", libraryTarget: "amd", path: path.resolve(__dirname, "build"), }, mode: "production", module: { rules: [ {parser: {System: false}}, { test: /.js?$/, exclude: [path.resolve(__dirname, "node_modules")], loader: "babel-loader", }, { test: /.css$/, exclude: [path.resolve(__dirname, "node_modules"), /.krem.css$/], use: [ "style-loader", { loader: "css-loader", options: { localIdentName: "[path][name]__[local]", }, }, { loader: "postcss-loader", options: { plugins() { return [ require("autoprefixer") ]; }, }, }, ], }, { test: /.css$/, include: [path.resolve(__dirname, "node_modules")], exclude: [/.krem.css$/], use: ["style-loader", "css-loader"], }, ], }, resolve: { modules: [ __dirname, "node_modules", ], }, plugins: [ CopyWebpackPlugin([ {from: path.resolve(__dirname, "src/index.html")}, {from: path.resolve(__dirname, "src/styles.css")}, ]), new CleanWebpackPlugin(["build"]), ], devtool: "source-map", externals: [ /^lodash$/, /^single-spa$/, /^rxjs/?.*$/, ], };
????????上面的配置中,最后的externals屬性值配置不需要webpack打包的依賴,因?yàn)檫@些在公共依賴中已經(jīng)打包好了,不需要多帶帶打包
????????在項(xiàng)目根目錄創(chuàng)建文件webpack.config.config.dev.js,內(nèi)容如下:
const config = require("./webpack.config.config.js") const webpack = require("webpack") config.plugins.push(new webpack.NamedModulesPlugin()); config.plugins.push(new webpack.HotModuleReplacementPlugin()); config.devServer = { contentBase: "./build", historyApiFallback: true, headers: { "Access-Control-Allow-Origin": "*", }, proxy: { "/common/": { target: "http://localhost:8234", pathRewrite: {"^/common" : ""} } } } config.mode = "development" module.exports = config;
????????同樣配置跨域
????????在package.json中添加命令,最終內(nèi)容如下
{ "name": "portal", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "start": "concurrently "npm run start:config" "npm run start:common-deps"", "start:config": "webpack-dev-server --config ./webpack.config.config.dev.js --port 8233", "start:common-deps": "webpack-dev-server --config ./webpack.common-deps.config.dev.js --port 8234", "build": "npm run build:config && npm run build:common-deps", "build:config": "webpack --config ./webpack.config.config.js -p", "build:common-deps": "webpack --config ./webpack.common-deps.config.js -p" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.4.3", "@babel/plugin-syntax-dynamic-import": "7.0.0", "@babel/preset-env": "^7.4.3", "babel-core": "6.26.3", "babel-loader": "8.0.0", "clean-webpack-plugin": "0.1.19", "concurrently": "^4.1.1", "copy-webpack-plugin": "4.5.2", "css-loader": "1.0.0", "style-loader": "0.23.0", "webpack": "4.17.1", "webpack-cli": "3.1.0", "webpack-dev-server": "^3.1.14" } }
????????至此,整個(gè)portal項(xiàng)目就搭建完畢了,下一篇,我們實(shí)現(xiàn)menu項(xiàng)目和project1項(xiàng)目
????????項(xiàng)目源碼
????????Portal源碼
????????微前端 —— 理論篇
????????微前端 —— menu&&project1(React)
????????微前端 —— project2項(xiàng)目(VUE)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106341.html
摘要:現(xiàn)在開(kāi)始從頭搭建我們的微前端架構(gòu)。項(xiàng)目源碼微前端項(xiàng)目微前端微前端項(xiàng)目 1. 微前端 ????????基于spa類的單頁(yè)應(yīng)用,隨著企業(yè)工程項(xiàng)目的體積越來(lái)越大,開(kāi)發(fā)的功能越來(lái)越多,頁(yè)面也越來(lái)越多,項(xiàng)目隨之也變得越來(lái)越臃腫,維護(hù)起來(lái)十分困難,往往改一個(gè)logo,或者改一個(gè)小樣式,都要將項(xiàng)目全部重新打包一遍,維護(hù)困難,部署也困難。 ????????因此前端在借鑒后端的微服務(wù)架構(gòu)模式后,衍生了...
摘要:前言微前端理論篇微前端項(xiàng)目微前端前一篇文章講解了項(xiàng)目在微前端架構(gòu)中的應(yīng)用,本篇為最后一篇,項(xiàng)目在此架構(gòu)中的應(yīng)用。項(xiàng)目我們就不自己搭建了,直接使用腳手架生成。 前言 ????????微前端 —— 理論篇????????微前端 —— portal項(xiàng)目????????微前端 —— menu&&project1(React)????????前一篇文章講解了react項(xiàng)目在single-spa微...
摘要:我們繼續(xù)沿用了原來(lái)就有的,借此把融入整個(gè)微前端框架,而已經(jīng)改造的則不需要我們的開(kāi)發(fā)團(tuán)隊(duì),分框架組和各個(gè)業(yè)務(wù)組。項(xiàng)目該項(xiàng)目是整個(gè)微前端項(xiàng)目的入口。本坑實(shí)踐它很大的理由也是用自己的方法初探微前端實(shí)踐方法的可行性。 在寫這篇文章的一個(gè)多月前,本坑還不知道微前端是什么,大概從字面上的含義是比較小的前端項(xiàng)目。 本坑開(kāi)始實(shí)踐它,是由于工作要求。改造一個(gè)運(yùn)行多年,前端用jsp寫的服務(wù)平臺(tái)項(xiàng)目(以下簡(jiǎn)...
摘要:前言微前端理論篇微前端項(xiàng)目上一篇中,我們完成了項(xiàng)目的搭建,算是完成了整個(gè)微前端架構(gòu)的一半工程了。項(xiàng)目項(xiàng)目是作為頁(yè)面的菜單顯示的,主要用于路由的控制。源碼地址源碼地址項(xiàng)目源碼地址微前端理論篇微前端項(xiàng)目微前端項(xiàng)目 前言 ????????微前端 —— 理論篇????????微前端 —— portal項(xiàng)目????????上一篇中,我們完成了portal項(xiàng)目的搭建,算是完成了整個(gè)微前端架構(gòu)的一半...
摘要:前端中的計(jì)算機(jī)領(lǐng)域的通常認(rèn)為起源于。并對(duì)其主要內(nèi)容作了自己的解讀。搬到另一個(gè)地區(qū)會(huì)導(dǎo)致名氣降低。年度報(bào)告,年最受歡迎的編程語(yǔ)言年上最流行的種編程語(yǔ)言及前十最火熱的項(xiàng)目排行榜,分別由及登頂。技術(shù)周刊由小組出品,匯聚一周好文章,周刊原文。 showImg(https://segmentfault.com/img/bVWHC4?w=1000&h=710); 本期推薦 反擊爬蟲(chóng),前端工程師的腦...
閱讀 1575·2021-11-24 09:39
閱讀 1064·2021-11-22 15:11
閱讀 2220·2021-11-19 11:35
閱讀 1643·2021-09-13 10:37
閱讀 2482·2021-09-03 10:47
閱讀 2166·2021-08-30 09:47
閱讀 1644·2021-08-20 09:39
閱讀 2924·2019-08-30 14:13