一般做網(wǎng)站是用什么程序做的烏魯木齊seo
長(zhǎng)夜漫漫,無心睡眠。心中所想,心中所感,憂愁當(dāng)前,就執(zhí)筆而下,寫下這篇文章。
回憶過往
回想當(dāng)初為啥學(xué)前端,走前端這條路,學(xué)校要求嘛,興趣愛好嘛,還是為了錢。 時(shí)間帶著我的回憶,回到了21年,也是我人生得轉(zhuǎn)折點(diǎn),那時(shí)候大學(xué)分班,直白點(diǎn)就是選擇路線,因?yàn)槲覀兪擒浖こ虒I(yè),所以軟件方面都學(xué)習(xí)過,軟件設(shè)計(jì)模式,數(shù)據(jù)結(jié)構(gòu),算法,計(jì)算機(jī)網(wǎng)咯,數(shù)據(jù)庫(kù),web程序設(shè)計(jì),計(jì)算機(jī)組成原理,項(xiàng)目管理,等等科目,甚至硬件我們也有實(shí)操,示波器,焊接,組裝板塊都玩了一下??梢哉f學(xué)的很雜,軟件工程專業(yè)得學(xué)生其實(shí)學(xué)得更多得都是偏后端得科目,像前端這種可能不入大學(xué)老師得眼,所以前端是沒有專門的課程得。當(dāng)時(shí)黑馬也來我們學(xué)校合作過,帶著我們寫項(xiàng)目,后端java,微服務(wù)。最讓我們印象深刻得是,他們培訓(xùn)畢業(yè)班工資情況,當(dāng)時(shí)很驚訝,月薪一萬,兩三萬都有。但是現(xiàn)在仔細(xì)想想那些都是外包公司,包裝了幾年工作經(jīng)驗(yàn)進(jìn)去的。是啊,當(dāng)時(shí),java后面,很高薪啊,而且上限總體要比前端高啊。大數(shù)據(jù)那時(shí)候也很火啊,甚至人工智能python也火。挺迷茫得,不僅是我,還有我的室友嘛。每個(gè)人得人生仿佛都在那時(shí)候決擇了。 我也問了很多身邊出去工作的人,建議都是選人工智能,大數(shù)據(jù),這些比較吃香。不過我們還是很理智得,人工智能選不得,沒有個(gè)研究生身份,選它很難找到工作,而且我們學(xué)校不出名。其實(shí)當(dāng)我們問別人得時(shí)候,心里已經(jīng)有個(gè)不確定得而想選擇得答案。對(duì)于我來說,大數(shù)據(jù),跟后端,我都能玩,只是感覺比較枯燥,相比于前端,頁(yè)面直接能看到,更加得吸引我的注意力,后端上限是高,但又有幾個(gè)能達(dá)到月薪五萬呢,我們更多得是平凡人,不是大牛。這就是我走了前端路線得答案,沒那么枯燥,可視化。
迷茫當(dāng)下
也許很多人轉(zhuǎn)行過來得學(xué)前端,是因?yàn)镮T得高薪工作,為啥不轉(zhuǎn)后端呢,因?yàn)橄鄬?duì)于后端,前端更好學(xué)點(diǎn)。這個(gè)不得不承認(rèn),我做兼職得時(shí)候,就遇到好多都是轉(zhuǎn)行過來得,然后花錢請(qǐng)教問題解決得。所以就造成了人員很多過來一起卷,大環(huán)境得不行,很多公司都在裁員,加上AI得出現(xiàn)。所以會(huì)搞得人心惶惶。工作幾年了,到了漲薪得年紀(jì),公司還降薪,很多人都都說大環(huán)境不好,能茍著就茍著,面試機(jī)會(huì)也少。 所以現(xiàn)在很多公司裁高低招,你不干自然有的是人干,造成行業(yè)內(nèi)卷加劇。 金三銀四,我也投了試一下,面了幾家公司,有一家公司讓我印象很深刻,深刻在什么地方呢,他問了我很底層,js底層,問我js怎么來的,如果不用它得已有api,讓你去判斷它是什么類型,你怎么判斷。當(dāng)時(shí)我回答上了引用數(shù)據(jù)類型,可以用原型連得方式去判斷。但是基本數(shù)據(jù)類型我就懵了,像0,好像用不了__prototo__吧,不過它確實(shí)有個(gè)API可以進(jìn)行獲取到它得原型對(duì)象,一生萬物,萬物皆對(duì)象,確實(shí)都可以用原型鏈來判斷。 他問了我?guī)讉€(gè)比較難得問題,最后我問他,你們公司是要搭建自己得框架嘛,還是做要插件,組件庫(kù)。一問啥都沒有,都在計(jì)劃中,聽了他的業(yè)務(wù)描述,純純的切圖崽就能完成得東西,干嘛問這種問題。我是有點(diǎn)想不通得。我也面了一家,本來說是人事面得,然后面試得時(shí)候又加技術(shù)面,一直在問我解決方案,然后我問他,我看你一直不滿意我的方案,你是有更好得方案嘛,能介紹一下嘛,然后他說的跟我前面差不多,總感覺是套我方案得感覺,然后就沒然后了。還是面試一些中大型公司比較好,我回答不好的時(shí)候,他能很清楚得解答給我聽。雖然沒過,但也讓我收獲不少。
提升自我
這段時(shí)間,我也陷入了迷茫,到底想活出怎樣的人生。 我也問過同事,他是怎么說的,我相信我的價(jià)值還是比人工智能要強(qiáng)的,大不了去擺地?cái)?。是?#xff0c;與其自我焦慮,不如,有空的時(shí)候提升自己。哪怕出去玩,都比精神內(nèi)耗強(qiáng),誰知道明天是怎樣的呢。還不如,靜下來提升自我。在思考一番后,我的靈感來了。最近一直沒寫作,也不是說擺爛了。而是沒有一個(gè)idea,自己要干嘛。想要干嘛。 因?yàn)橹白隽藘蓚€(gè)公司的項(xiàng)目,跟同事寫了六七款日歷組件,所以就想能不能寫一個(gè)日歷庫(kù),因?yàn)槎际且苿?dòng)端的,Taro開發(fā)的,網(wǎng)上沒找到一個(gè)模板,公司也在弄移動(dòng)端組件庫(kù),剛好我也參與其中,所以我也能一邊學(xué)習(xí) ,一邊弄個(gè)自己的作品。所以我就自己搭建一個(gè)。
總體設(shè)計(jì)
構(gòu)想
搭建框架 => 構(gòu)建總體目錄 => 編寫組件 => 組件測(cè)試 => 打包發(fā)布 => 網(wǎng)站展示 =>網(wǎng)站設(shè)計(jì),網(wǎng)站展示,mark展示代碼,代碼高亮復(fù)制,例子渲染,錨點(diǎn)展示,接口文檔,兼容打包發(fā)布 => 進(jìn)行部署。
當(dāng)時(shí)我的構(gòu)思是這樣的,當(dāng)時(shí)組件的打包,跟網(wǎng)站還是不一樣的。所以我就考慮從vite,webpack,rollup三個(gè)其中一個(gè)進(jìn)行打包,因?yàn)閞ollup不是很熟悉,就打算用它來打包,也是抱著一個(gè)學(xué)習(xí)的心,。然后網(wǎng)站的打包就用taro自帶配置的進(jìn)行打包,當(dāng)然內(nèi)置的是webpack。
先上效果圖,畢竟前端要最后呈現(xiàn)的東西為主。
使用技術(shù):Taro + React + Ts +React-router-dom + rollup + webpack5
效果圖
1.常用日歷組件
2.帶彈窗日歷組件
3.滑動(dòng)日歷組件
4.簡(jiǎn)單日歷組件
5.選項(xiàng)日歷組件
6.星期日歷組件
目前展示這幾個(gè)組件。等有其它想法繼續(xù)添加。
預(yù)覽地址:地址
目錄結(jié)構(gòu):
wskCalendar
├─ config //taro配置
│ ├─ dev.ts
│ ├─ index.ts
│ └─ prod.ts
├─ src
│ ├─ api
│ │ └─ test.ts
│ ├─ components //日歷組件
│ ├─ images //日歷組件圖片
│ ├─ index.html
│ ├─ index.ts //日歷組件打包入口
│ ├─ pages //測(cè)試展示入口
│ ├─ routes //配置測(cè)試路由
│ ├─ style //樣式
│ │ ├─ common.scss
│ │ ├─ index.scss
│ │ └─ website.scss //網(wǎng)站全局樣式
│ ├─ types
│ ├─ utils //工具函數(shù)
│ └─ website //網(wǎng)站架構(gòu)
│ ├─ assets //網(wǎng)站資源
│ │ └─ images
│ ├─ components//展示組件編寫
│ ├─ guide//指南
│ ├─ home//首頁(yè)
│ ├─ index
│ ├─ layoutCom//部局組件
│ └─ routers//路由
│ ├─ demoRoutes.ts
│ ├─ index.ts
│ ├─ sidebarTabs.ts
│ ├─ topbarTabs.ts
│ └─ websiteRoutes.ts
├─ .editorconfig
├─ .eslintrc
├─ .gitignore
├─ babel.config.js
├─ buildJson.js //處理package.joson
├─ copy-rollup-postcss-inject-to-css.mjs//自己編寫的插件處理scss
├─ jest.config.ts
├─ markdown-loader.js//自己編寫插件處理md文件
├─ myRollupPlugin.mjs
├─ package.json
├─ project.config.json
├─ project.tt.json
├─ README.md
├─ rollup.config.mjs
├─ tsconfig.json
├─ types
├─ yarn.lock
插件編寫
buildJson.js 處理打包package.json寫入插件,type:'module’必須是這個(gè)配置在這里,不然Taro的Api沒辦法使用,這個(gè)問題我找了一天,這也是taro的一個(gè)坑。移除自己的插件避免下載依賴進(jìn)行了套娃處理。
const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const __dirnameNew = __dirname;
let rootPath = path.join(__dirnameNew, 'package.json');
let filePath = path.join(__dirnameNew, 'dist', 'wskCalendar', 'package.json');
// 創(chuàng)建持久化編譯時(shí)間
const createPersistentCompilationTime = () => {// 1.判斷是否存在文件try {getTimeFile();} catch (error) { }
};
// 2.獲取時(shí)間文件
const getTimeFile = () => {try {fs.readFile(rootPath, "utf-8", (err, fileData) => {fileWriteContent(fileData);});} catch (error) {}
};
// 文件寫入內(nèi)容
const fileWriteContent = (data) => { //寫入type:moduletry {// 解析 JSON 字符串為對(duì)象let jsonData = JSON.parse(data);// 新建對(duì)象let newJsonData = {};// 遍歷舊對(duì)象的鍵for (let key in jsonData) {// 把每個(gè)鍵/值對(duì)添加到新對(duì)象newJsonData[key] = jsonData[key];// 在 description 后面添加新的鍵/值對(duì)if (key === "description") {newJsonData["type"] = "module";}if (key === "dependencies") {delete newJsonData["dependencies"]?.["wskcalendar"] //刪除自己的依賴包防止下載套娃}}// 把對(duì)象轉(zhuǎn)回 JSON 字符串,并保持原來的格式data = JSON.stringify(newJsonData, null, 2);fs.writeFile(filePath, Buffer.from(data, 'utf-8'), "utf-8", (err) => {if (err) {return console.warn(`🚀[developer 🌞🔥 (っ °Д °;)っ]🌈 ~ file: buildJson.js:31 ~ fs.writeFile ~ err: 寫入文件失敗`, err);} else {return console.warn(`🚀[developer 🌞🔥 (っ °Д °;)っ]🌈 ~ :\b ? json寫入成功, 請(qǐng)進(jìn)入目錄 ${chalk.red("cd dist/wskCalendar")} 進(jìn)行發(fā)布新版本:\b ${chalk.green("npm publish")}\b 返回:${chalk.green("cd ../..")}\b ? 撤銷版本請(qǐng)使用:\b ${chalk.yellow("npm unpublish wskCalendar@[指定版本號(hào)]")}\b 插件地址`);}});} catch (error) {console.warn("🚀[ developer wsj ] ~ file: buildTime.ts:37 ~ fileWriteContent ~ error:",error);}
};
createPersistentCompilationTime();
markdown-loader.js 進(jìn)行一個(gè)提取md,文件進(jìn)行渲染,以及高亮處理.
const marked = require('marked');
const hljs = require('highlight.js');
module.exports = content => {const __jsx = content.match(/```jsx[\s\S]*```/g)?.[0]?.replaceAll(/```jsx|```/g, '') || 'export const Jsx = () => <></>;';const __html = marked.marked(content, {// 設(shè)置代碼高亮highlight: function (code, lang) {const language = hljs.getLanguage(lang) ? lang : 'plaintext';return hljs.highlight(code, { language }).value;},});return `${__jsx}export const __html = ` + '`' + __html + '`;' +'export const __code = `' + __jsx + '`;';
}
copy-rollup-postcss-inject-to-css.mjs 將CSS、SCSS或LESS樣式從打包的JavaScript文件中截取并放入單獨(dú)的CSS文件。這樣做的好處是,可以避免將樣式加載到JavaScript中,從而提高頁(yè)面的加載速度。
因?yàn)闃邮轿募J(rèn)是在瀏覽器解析和執(zhí)行JavaScript代碼之前加載的,所以,將樣式文件獨(dú)立出來可以盡快給用戶展示頁(yè)面的樣式,同時(shí)避免JavaScript執(zhí)行阻塞頁(yè)面的顯示。
import { createFilter } from '@rollup/pluginutils';function inlineToExtract (options = {}) {const filter = createFilter(options.include, options.exclude);return {name: 'inline-to-extract',transform (_, id) {if (!filter(id)) return null},generateBundle (_, bundle) {const resolveCss = [];Object.keys(bundle).forEach(name => {const bundleItem = bundle[name];bundleItem.imports?.forEach((item, index) => {if (/(scss|less|css)\.js/.test(item)) {let code;code = /"[\s\S^"]*"/igm.exec(bundle[item].code);if (code?.[0]) {code = code[0].replace(/\\n/g, '').replace(/\\"/g, '"').replace(/\\\\/g, '\\');if (!resolveCss.includes(item)) {Object.assign(bundle[item], {fileName: item.replace(/\.(scss|less|css)\.js/, '.css'),code: code.slice(1, code.length - 1),importedBindings: null,imports: []});resolveCss.push(item);}}delete bundleItem.importedBindings[item];bundleItem.importedBindings[item.replace(/\.(scss|less|css)\.js/, '.css')] = [];bundleItem.imports[index] = bundleItem.imports[index].replace(/\.(scss|less|css)\.js/, '.css');bundleItem.code = bundleItem.code.replace(/\.(scss|less|css)\.js/, '.css');}});});}}
}export default inlineToExtract;
myRollupPlugin.mjs偉大而不現(xiàn)實(shí)的構(gòu)想插件,個(gè)人構(gòu)想,就是進(jìn)行插件把Taro相關(guān)的組件轉(zhuǎn)換為HTML元素,這樣就不用基于taro框架去運(yùn)行起來了,在任何的一個(gè)react框架上都可以用了,其它的方案都是兩套代碼,我懶得寫,但是組件做到了轉(zhuǎn)換,忘記了Taro Api,唉,阿康能力有限還是處理不了taro api的轉(zhuǎn)換。嘗試了將taro.js打包進(jìn)去了還是不行。
import { createFilter } from 'rollup-pluginutils';
import * as parser from '@babel/parser';
import traverse from '@babel/traverse';
import generate from '@babel/generator';
import * as t from '@babel/types';export default function replaceTagsAndRemoveNonExistentProps() {const filter = createFilter('**/*.tsx', 'node_modules/**');return {name: 'replace-tags-and-remove-non-existent-props',transform(code, id) {if (!filter(id)) return;const ast = parser.parse(code, {sourceType: 'module',plugins: ['jsx', 'typescript'],});traverse.default(ast, {JSXOpeningElement(path) {if (['View', 'Text', 'Image', 'ScrollView'].includes(path.node.name.name)) {if (path.node.name.name === 'View') path.node.name.name = 'div';if (path.node.name.name === 'Text') path.node.name.name = 'span';if (path.node.name.name === 'Image') path.node.name.name = 'img';if (path.node.name.name === 'ScrollView') path.node.name.name = 'div';// 過濾并替換屬性path.node.attributes = path.node.attributes.filter(attr => {if (!attr.name) return false;let propName = attr.name.name;if (propName === 'catchMove') return false; // 移除 'catchMove';if(propName === 'scrollIntoView') return false;if(propName === 'scrollX') return false;attr.value && replaceITouchEvent(attr.value);return true;});}},JSXClosingElement(path) {if (['View', 'Text', 'Image', 'ScrollView'].includes(path.node.name.name)) {if (path.node.name.name === 'View') path.node.name.name = 'div';if (path.node.name.name === 'Text') path.node.name.name = 'span';if (path.node.name.name === 'Image') path.node.name.name = 'img';if (path.node.name.name === 'ScrollView') path.node.name.name = 'div';}},CallExpression(path) {if (t.isIdentifier(path.node.callee) && ['onTouchMove', 'onTouchStart', 'onTouchEnd'].includes(path.node.callee.name)) {path.node.arguments = path.node.arguments.map(arg => replaceITouchEvent(arg));}},TSTypeReference(path) {path.replaceWith(replaceITouchEvent(path.node));},ArrowFunctionExpression(path) {path.node.params.forEach(param => {if (t.isTSTypeAnnotation(param.typeAnnotation) &&t.isTSTypeReference(param.typeAnnotation.typeAnnotation)) {param.typeAnnotation.typeAnnotation = replaceITouchEvent(param.typeAnnotation.typeAnnotation);}});},});const output = generate.default(ast, {}, code);return {code: output.code,map: { mappings: '' }};},};
}function replaceITouchEvent(node) {if (t.isTSTypeReference(node)) {if (node.typeName && t.isIdentifier(node.typeName) && node.typeName.name === 'ITouchEvent') {// 創(chuàng)建一個(gè)新的類型引用,使用 `React.TouchEvent` 作為類型名,并設(shè)置類型參數(shù)為 `HTMLDivElement`return t.tsTypeReference(t.identifier('React.TouchEvent'),t.tsTypeParameterInstantiation([t.tsTypeReference(t.identifier('HTMLDivElement'))]));}}return node;
}
對(duì)于項(xiàng)目的介紹就暫時(shí)那么多,具體的請(qǐng)看項(xiàng)目,后附上github地址,但是還有一個(gè)坑,也是taro的prebundle 為 true 時(shí),Taro 會(huì)對(duì)所有 npm 包和本地 npm 包進(jìn)行預(yù)編譯(pre-bundling)。對(duì)于一些 npm 包來說,有時(shí)候你可能直接把它們作為 @tarojs/components 或其他庫(kù)的附屬品導(dǎo)入到你的項(xiàng)目中,而這些包在進(jìn)行模塊導(dǎo)入時(shí)可能會(huì)存在一些問題,比如使用了一些關(guān)鍵字或者語(yǔ)法結(jié)構(gòu)等。這時(shí),把 prebundle 設(shè)置為 true 就會(huì)對(duì)這些包做一次預(yù)編譯,旨在避免可能的編譯錯(cuò)誤,增強(qiáng)模塊的兼容性。
不然打包出來的網(wǎng)站使用taro的api有問題。
最后吐槽:taro這個(gè)框架說句心理實(shí)話,坑挺多的, 也不能說是坑,只能說開發(fā)心智負(fù)擔(dān)有點(diǎn)重。
倉(cāng)庫(kù)地址:github
這個(gè)插件可以為你提供一個(gè)是編寫自己的移動(dòng)端插件,跟組件庫(kù)的思路,缺點(diǎn),像mark暫時(shí)只能支持js的jsx展示示例代碼,跟局限于react,taro上。如果覺得不錯(cuò),可以給點(diǎn)個(gè)star。
以上就是我的一個(gè)靈感實(shí)現(xiàn)的的過程。也許比較拉跨,但也是一次自我的提升。后面也會(huì)嘗試著去學(xué)習(xí)一下AI大模型
做技術(shù)的學(xué)的技術(shù)一定要順應(yīng)時(shí)代的發(fā)展,社會(huì)需要什么黑科技,就要花時(shí)間去鉆研。我知道現(xiàn)在不努力積累自己的專業(yè)知識(shí),未來只會(huì)如逆水行舟,一步步將我推回起點(diǎn)。疫情三年真的是大浪淘沙,淘汰只會(huì)是那些不腳踏實(shí)地學(xué)習(xí)和工作的人,出來混遲早要還的。只有現(xiàn)在奮力前行,未來才有更多的選擇機(jī)會(huì)。
最后
誰的青春不迷茫,迷茫下只能是順勢(shì)而為,不斷提升自己。迷茫中不忘初心,堅(jiān)持心中得所想,不斷進(jìn)步。當(dāng)然特別迷茫得時(shí)候,去吹吹海風(fēng),去看看路上得風(fēng)景,說不定哪一天風(fēng)告訴了你答案,你一瞬間就明白了自己想要什么樣得人生。最近宮崎駿,新出了一部動(dòng)漫《你想活出怎樣得人生》看看別人得人生,說不定也有你想有得答案。每個(gè)人想法都是不一樣得,想要得人生也不一樣。有點(diǎn)雞湯了哈,言而總之,迷茫下還是要提升自我,不管是前端,還是其它得都好。