commit
83504f495b
26 changed files with 649 additions and 349 deletions
After Width: | Height: | Size: 1.0 MiB |
@ -1,3 +1,3 @@ |
||||
<div class='leading-relaxed text-left p-4 text-md text-gray-800 border-t border-t-gray-300 bg-gray-100 rounded-bl-md rounded-br-md'> |
||||
<div class='text-sm sm:text-base leading-relaxed text-left p-2 sm:p-4 text-md text-gray-800 border-t border-t-gray-300 bg-gray-100 rounded-bl-md rounded-br-md'> |
||||
<slot /> |
||||
</div> |
@ -1,204 +1,219 @@ |
||||
export class Topic { |
||||
constructor() { |
||||
this.overlayId = 'topic-overlay'; |
||||
this.contentId = 'topic-content'; |
||||
this.loaderId = 'topic-loader'; |
||||
this.topicBodyId = 'topic-body'; |
||||
this.topicActionsId = 'topic-actions'; |
||||
this.markTopicDoneId = 'mark-topic-done'; |
||||
this.markTopicPendingId = 'mark-topic-pending'; |
||||
this.closeTopicId = 'close-topic'; |
||||
|
||||
this.activeRoadmapId = null; |
||||
this.activeTopicId = null; |
||||
|
||||
this.handleTopicClick = this.handleTopicClick.bind(this); |
||||
|
||||
this.close = this.close.bind(this); |
||||
this.resetDOM = this.resetDOM.bind(this); |
||||
this.populate = this.populate.bind(this); |
||||
this.handleOverlayClick = this.handleOverlayClick.bind(this); |
||||
this.markAsDone = this.markAsDone.bind(this); |
||||
this.markAsPending = this.markAsPending.bind(this); |
||||
this.queryRoadmapElementsByTopicId = this.queryRoadmapElementsByTopicId.bind(this); |
||||
|
||||
this.init = this.init.bind(this); |
||||
} |
||||
|
||||
get loaderEl() { |
||||
return document.getElementById(this.loaderId); |
||||
} |
||||
|
||||
get markTopicDoneEl() { |
||||
return document.getElementById(this.markTopicDoneId); |
||||
} |
||||
|
||||
get markTopicPendingEl() { |
||||
return document.getElementById(this.markTopicPendingId); |
||||
} |
||||
|
||||
get topicActionsEl() { |
||||
return document.getElementById(this.topicActionsId); |
||||
} |
||||
|
||||
get contentEl() { |
||||
return document.getElementById(this.contentId); |
||||
} |
||||
|
||||
get overlayEl() { |
||||
return document.getElementById(this.overlayId); |
||||
} |
||||
|
||||
resetDOM(hideOverlay = false) { |
||||
if (hideOverlay) { |
||||
this.overlayEl.classList.add('hidden'); |
||||
} else { |
||||
this.overlayEl.classList.remove('hidden'); |
||||
} |
||||
|
||||
this.loaderEl.classList.remove('hidden'); // Show loader
|
||||
this.topicActionsEl.classList.add('hidden'); // Hide Actions
|
||||
this.contentEl.replaceChildren(''); // Remove content
|
||||
} |
||||
|
||||
close() { |
||||
this.resetDOM(true); |
||||
|
||||
this.activeRoadmapId = null; |
||||
this.activeTopicId = null; |
||||
} |
||||
|
||||
/** |
||||
* @param {string | HTMLElement} html |
||||
*/ |
||||
populate(html) { |
||||
this.contentEl.replaceChildren(html); |
||||
this.loaderEl.classList.add('hidden'); |
||||
this.topicActionsEl.classList.remove('hidden'); |
||||
|
||||
const normalizedGroup = (this.activeTopicId || '').replace(/^\d+-/, ''); |
||||
const isDone = localStorage.getItem(normalizedGroup) === 'done'; |
||||
|
||||
if (isDone) { |
||||
this.markTopicDoneEl.classList.add('hidden'); |
||||
this.markTopicPendingEl.classList.remove('hidden'); |
||||
} else { |
||||
this.markTopicDoneEl.classList.remove('hidden'); |
||||
this.markTopicPendingEl.classList.add('hidden'); |
||||
} |
||||
} |
||||
|
||||
fetchTopicHtml(roadmapId, topicId) { |
||||
const topicPartial = topicId.replace(/^\d+-/, '').replaceAll(/:/g, '/'); |
||||
const fullUrl = `/${roadmapId}/${topicPartial}/`; |
||||
|
||||
return fetch(fullUrl) |
||||
.then((res) => { |
||||
return res.text(); |
||||
}) |
||||
.then((topicHtml) => { |
||||
// It's full HTML with page body, head etc.
|
||||
// We only need the inner HTML of the #main-content
|
||||
const node = new DOMParser().parseFromString(topicHtml, 'text/html'); |
||||
|
||||
return node.getElementById('main-content'); |
||||
}); |
||||
} |
||||
|
||||
handleTopicClick(e) { |
||||
const { roadmapId, topicId } = e.detail; |
||||
if (!topicId || !roadmapId) { |
||||
console.log('Missing topic or roadmap: ', e.detail); |
||||
return; |
||||
} |
||||
|
||||
this.activeRoadmapId = roadmapId; |
||||
this.activeTopicId = topicId; |
||||
|
||||
if (/^ext_link/.test(topicId)) { |
||||
window.open(`https://${topicId.replace('ext_link:', '')}`); |
||||
return; |
||||
} |
||||
|
||||
this.resetDOM(); |
||||
this.fetchTopicHtml(roadmapId, topicId) |
||||
.then((content) => { |
||||
this.populate(content); |
||||
}) |
||||
.catch((e) => { |
||||
console.error(e); |
||||
this.populate('Error loading the content!'); |
||||
}); |
||||
} |
||||
|
||||
queryRoadmapElementsByTopicId(topicId) { |
||||
const elements = document.querySelectorAll(`[data-group-id$="-${topicId}"]`); |
||||
const matchingElements = []; |
||||
|
||||
elements.forEach((element) => { |
||||
const foundGroupId = element?.dataset?.groupId || ''; |
||||
const validGroupRegex = new RegExp(`^\\d+-${topicId}$`); |
||||
|
||||
if (validGroupRegex.test(foundGroupId)) { |
||||
matchingElements.push(element); |
||||
} |
||||
}); |
||||
|
||||
return matchingElements; |
||||
constructor() { |
||||
this.overlayId = 'topic-overlay'; |
||||
this.contentId = 'topic-content'; |
||||
this.loaderId = 'topic-loader'; |
||||
this.topicBodyId = 'topic-body'; |
||||
this.topicActionsId = 'topic-actions'; |
||||
this.markTopicDoneId = 'mark-topic-done'; |
||||
this.markTopicPendingId = 'mark-topic-pending'; |
||||
this.closeTopicId = 'close-topic'; |
||||
this.contributionTextId = 'contrib-meta'; |
||||
|
||||
this.activeRoadmapId = null; |
||||
this.activeTopicId = null; |
||||
|
||||
this.handleTopicClick = this.handleTopicClick.bind(this); |
||||
|
||||
this.close = this.close.bind(this); |
||||
this.resetDOM = this.resetDOM.bind(this); |
||||
this.populate = this.populate.bind(this); |
||||
this.handleOverlayClick = this.handleOverlayClick.bind(this); |
||||
this.markAsDone = this.markAsDone.bind(this); |
||||
this.markAsPending = this.markAsPending.bind(this); |
||||
this.queryRoadmapElementsByTopicId = |
||||
this.queryRoadmapElementsByTopicId.bind(this); |
||||
|
||||
this.init = this.init.bind(this); |
||||
} |
||||
|
||||
get loaderEl() { |
||||
return document.getElementById(this.loaderId); |
||||
} |
||||
|
||||
get markTopicDoneEl() { |
||||
return document.getElementById(this.markTopicDoneId); |
||||
} |
||||
|
||||
get markTopicPendingEl() { |
||||
return document.getElementById(this.markTopicPendingId); |
||||
} |
||||
|
||||
get topicActionsEl() { |
||||
return document.getElementById(this.topicActionsId); |
||||
} |
||||
|
||||
get contributionTextEl() { |
||||
return document.getElementById(this.contributionTextId); |
||||
} |
||||
|
||||
get contentEl() { |
||||
return document.getElementById(this.contentId); |
||||
} |
||||
|
||||
get overlayEl() { |
||||
return document.getElementById(this.overlayId); |
||||
} |
||||
|
||||
resetDOM(hideOverlay = false) { |
||||
if (hideOverlay) { |
||||
this.overlayEl.classList.add('hidden'); |
||||
} else { |
||||
this.overlayEl.classList.remove('hidden'); |
||||
} |
||||
|
||||
this.loaderEl.classList.remove('hidden'); // Show loader
|
||||
this.topicActionsEl.classList.add('hidden'); // Hide Actions
|
||||
this.contributionTextEl.classList.add('hidden'); // Hide contribution text
|
||||
this.contentEl.replaceChildren(''); // Remove content
|
||||
} |
||||
|
||||
close() { |
||||
this.resetDOM(true); |
||||
|
||||
this.activeRoadmapId = null; |
||||
this.activeTopicId = null; |
||||
} |
||||
|
||||
/** |
||||
* @param {string | HTMLElement} html |
||||
*/ |
||||
populate(html) { |
||||
this.contentEl.replaceChildren(html); |
||||
this.loaderEl.classList.add('hidden'); |
||||
this.topicActionsEl.classList.remove('hidden'); |
||||
this.contributionTextEl.classList.remove('hidden'); |
||||
|
||||
const normalizedGroup = (this.activeTopicId || '').replace(/^\d+-/, ''); |
||||
const isDone = localStorage.getItem(normalizedGroup) === 'done'; |
||||
|
||||
if (isDone) { |
||||
this.markTopicDoneEl.classList.add('hidden'); |
||||
this.markTopicPendingEl.classList.remove('hidden'); |
||||
} else { |
||||
this.markTopicDoneEl.classList.remove('hidden'); |
||||
this.markTopicPendingEl.classList.add('hidden'); |
||||
} |
||||
|
||||
markAsDone(topicId) { |
||||
const updatedTopicId = topicId.replace(/^\d+-/, ''); |
||||
localStorage.setItem(updatedTopicId, 'done'); |
||||
|
||||
this.queryRoadmapElementsByTopicId(updatedTopicId).forEach((item) => { |
||||
item?.classList?.add('done'); |
||||
} |
||||
|
||||
fetchTopicHtml(roadmapId, topicId) { |
||||
const topicPartial = topicId.replace(/^\d+-/, '').replaceAll(/:/g, '/'); |
||||
const fullUrl = `/${roadmapId}/${topicPartial}/`; |
||||
|
||||
return fetch(fullUrl) |
||||
.then((res) => { |
||||
return res.text(); |
||||
}) |
||||
.then((topicHtml) => { |
||||
// It's full HTML with page body, head etc.
|
||||
// We only need the inner HTML of the #main-content
|
||||
const node = new DOMParser().parseFromString(topicHtml, 'text/html'); |
||||
|
||||
return node.getElementById('main-content'); |
||||
}); |
||||
} |
||||
|
||||
markAsPending(topicId) { |
||||
const updatedTopicId = topicId.replace(/^\d+-/, ''); |
||||
|
||||
localStorage.removeItem(updatedTopicId); |
||||
this.queryRoadmapElementsByTopicId(updatedTopicId).forEach((item) => { |
||||
item?.classList?.remove('done'); |
||||
} |
||||
|
||||
handleTopicClick(e) { |
||||
const { roadmapId, topicId } = e.detail; |
||||
if (!topicId || !roadmapId) { |
||||
console.log('Missing topic or roadmap: ', e.detail); |
||||
return; |
||||
} |
||||
|
||||
this.activeRoadmapId = roadmapId; |
||||
this.activeTopicId = topicId; |
||||
|
||||
if (/^ext_link/.test(topicId)) { |
||||
window.open(`https://${topicId.replace('ext_link:', '')}`); |
||||
return; |
||||
} |
||||
|
||||
this.resetDOM(); |
||||
this.fetchTopicHtml(roadmapId, topicId) |
||||
.then((content) => { |
||||
this.populate(content); |
||||
}) |
||||
.catch((e) => { |
||||
console.error(e); |
||||
this.populate('Error loading the content!'); |
||||
}); |
||||
} |
||||
|
||||
handleOverlayClick(e) { |
||||
const isClickedInsideTopic = e.target.closest(`#${this.topicBodyId}`); |
||||
|
||||
if (!isClickedInsideTopic) { |
||||
this.close(); |
||||
return; |
||||
} |
||||
|
||||
const isClickedDone = e.target.id === this.markTopicDoneId || e.target.closest(`#${this.markTopicDoneId}`); |
||||
if (isClickedDone) { |
||||
this.markAsDone(this.activeTopicId); |
||||
this.close(); |
||||
} |
||||
|
||||
const isClickedPending = e.target.id === this.markTopicPendingId || e.target.closest(`#${this.markTopicPendingId}`); |
||||
if (isClickedPending) { |
||||
this.markAsPending(this.activeTopicId); |
||||
this.close(); |
||||
} |
||||
|
||||
queryRoadmapElementsByTopicId(topicId) { |
||||
const elements = document.querySelectorAll( |
||||
`[data-group-id$="-${topicId}"]` |
||||
); |
||||
const matchingElements = []; |
||||
|
||||
elements.forEach((element) => { |
||||
const foundGroupId = element?.dataset?.groupId || ''; |
||||
const validGroupRegex = new RegExp(`^\\d+-${topicId}$`); |
||||
|
||||
if (validGroupRegex.test(foundGroupId)) { |
||||
matchingElements.push(element); |
||||
} |
||||
|
||||
const isClickedClose = e.target.id === this.closeTopicId || e.target.closest(`#${this.closeTopicId}`); |
||||
if (isClickedClose) { |
||||
}); |
||||
|
||||
return matchingElements; |
||||
} |
||||
|
||||
markAsDone(topicId) { |
||||
const updatedTopicId = topicId.replace(/^\d+-/, ''); |
||||
localStorage.setItem(updatedTopicId, 'done'); |
||||
|
||||
this.queryRoadmapElementsByTopicId(updatedTopicId).forEach((item) => { |
||||
item?.classList?.add('done'); |
||||
}); |
||||
} |
||||
|
||||
markAsPending(topicId) { |
||||
const updatedTopicId = topicId.replace(/^\d+-/, ''); |
||||
|
||||
localStorage.removeItem(updatedTopicId); |
||||
this.queryRoadmapElementsByTopicId(updatedTopicId).forEach((item) => { |
||||
item?.classList?.remove('done'); |
||||
}); |
||||
} |
||||
|
||||
handleOverlayClick(e) { |
||||
const isClickedInsideTopic = e.target.closest(`#${this.topicBodyId}`); |
||||
|
||||
if (!isClickedInsideTopic) { |
||||
this.close(); |
||||
return; |
||||
} |
||||
|
||||
const isClickedDone = |
||||
e.target.id === this.markTopicDoneId || |
||||
e.target.closest(`#${this.markTopicDoneId}`); |
||||
if (isClickedDone) { |
||||
this.markAsDone(this.activeTopicId); |
||||
this.close(); |
||||
} |
||||
|
||||
const isClickedPending = |
||||
e.target.id === this.markTopicPendingId || |
||||
e.target.closest(`#${this.markTopicPendingId}`); |
||||
if (isClickedPending) { |
||||
this.markAsPending(this.activeTopicId); |
||||
this.close(); |
||||
} |
||||
|
||||
const isClickedClose = |
||||
e.target.id === this.closeTopicId || |
||||
e.target.closest(`#${this.closeTopicId}`); |
||||
if (isClickedClose) { |
||||
this.close(); |
||||
} |
||||
} |
||||
|
||||
init() { |
||||
window.addEventListener('topic.click', this.handleTopicClick); |
||||
window.addEventListener('click', this.handleOverlayClick); |
||||
window.addEventListener('keydown', (e) => { |
||||
if (e.key.toLowerCase() === 'escape') { |
||||
this.close(); |
||||
} |
||||
} |
||||
|
||||
init() { |
||||
window.addEventListener('topic.click', this.handleTopicClick); |
||||
window.addEventListener('click', this.handleOverlayClick); |
||||
window.addEventListener('keydown', (e) => { |
||||
if (e.key.toLowerCase() === 'escape') { |
||||
this.close(); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
|
@ -1,31 +1,69 @@ |
||||
--- |
||||
import Icon from "./Icon.astro"; |
||||
import Loader from "./Loader.astro"; |
||||
import Icon from './Icon.astro'; |
||||
import Loader from './Loader.astro'; |
||||
|
||||
export interface Props { |
||||
roadmapId: string; |
||||
} |
||||
|
||||
const { roadmapId } = Astro.props; |
||||
const githubLink = `https://github.com/kamranahmedse/developer-roadmap/tree/master/src/roadmaps/${roadmapId}/content`; |
||||
--- |
||||
|
||||
<div id='topic-overlay' class='hidden'> |
||||
<div class="fixed top-0 right-0 z-40 h-screen p-4 sm:p-6 overflow-y-auto bg-white w-full sm:max-w-[600px]" tabindex="-1" id='topic-body'> |
||||
<div id='topic-loader' class='hidden'> |
||||
<Loader /> |
||||
</div> |
||||
|
||||
<div id='topic-actions' class='hidden mb-2'> |
||||
<button id='mark-topic-done' class='bg-green-600 text-white p-1 px-2 text-sm rounded-md hover:bg-green-700 inline-flex items-center'> |
||||
<Icon icon="check" /> <span class='ml-2'>Mark as Done</span> |
||||
</button> |
||||
|
||||
<button id='mark-topic-pending' class='hidden bg-red-600 text-white p-1 px-2 text-sm rounded-md hover:bg-red-700 inline-flex items-center'> |
||||
<Icon icon="reset" /> <span class='ml-2'>Mark as Pending</span> |
||||
</button> |
||||
|
||||
<button type="button" id='close-topic' class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center"> |
||||
<Icon icon="close" /> |
||||
</button> |
||||
</div> |
||||
|
||||
<div id='topic-content' class='prose prose-h1:mt-7 prose-h1:mb-2.5 prose-p:mt-0 prose-p:mb-2 prose-li:m-0 prose-li:mb-0.5 prose-h2:mb-3 prose-h2:mt-0'></div> |
||||
<div |
||||
class='fixed top-0 right-0 z-40 h-screen p-4 sm:p-6 overflow-y-auto bg-white w-full sm:max-w-[600px]' |
||||
tabindex='-1' |
||||
id='topic-body' |
||||
> |
||||
<div id='topic-loader' class='hidden'> |
||||
<Loader /> |
||||
</div> |
||||
|
||||
<div id='topic-actions' class='hidden mb-2'> |
||||
<button |
||||
id='mark-topic-done' |
||||
class='bg-green-600 text-white p-1 px-2 text-sm rounded-md hover:bg-green-700 inline-flex items-center' |
||||
> |
||||
<Icon icon='check' /> |
||||
<span class='ml-2'>Mark as Done</span> |
||||
</button> |
||||
|
||||
<button |
||||
id='mark-topic-pending' |
||||
class='hidden bg-red-600 text-white p-1 px-2 text-sm rounded-md hover:bg-red-700 inline-flex items-center' |
||||
> |
||||
<Icon icon='reset' /> |
||||
<span class='ml-2'>Mark as Pending</span> |
||||
</button> |
||||
|
||||
<button |
||||
type='button' |
||||
id='close-topic' |
||||
class='text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center' |
||||
> |
||||
<Icon icon='close' /> |
||||
</button> |
||||
</div> |
||||
<div class="bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-30"></div> |
||||
|
||||
<div |
||||
id='topic-content' |
||||
class='prose prose-h1:mt-7 prose-h1:mb-2.5 prose-p:mt-0 prose-p:mb-2 prose-li:m-0 prose-li:mb-0.5 prose-h2:mb-3 prose-h2:mt-0' |
||||
> |
||||
</div> |
||||
|
||||
<p |
||||
id='contrib-meta' |
||||
class='text-gray-400 text-sm border-t pt-3 mt-10 hidden' |
||||
> |
||||
We are still working on this page. You can contribute by submitting a |
||||
brief description and a few links to learn more about this topic <a |
||||
target='_blank' |
||||
class='underline text-blue-700' |
||||
href={githubLink}>on GitHub repository.</a |
||||
>. |
||||
</p> |
||||
</div> |
||||
<div class='bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-30'> |
||||
</div> |
||||
|
||||
</div> |
||||
|
@ -1,12 +1,33 @@ |
||||
--- |
||||
import Icon from "./Icon.astro"; |
||||
import Icon from './Icon.astro'; |
||||
--- |
||||
|
||||
<div class='sticky top-0 border-b border-b-yellow-300 z-10 flex h-[37px]' id='sticky-youtube-banner'> |
||||
<a href='https://youtube.com/theroadmap?sub_confirmation=1' target='_blank' class='flex bg-yellow-200 text-center flex-1 items-center justify-center text-sm hover:bg-yellow-300 outline-0 '> |
||||
<Icon icon="youtube" class="mr-2" /> We now have a YouTube Channel. <span class='hidden sm:inline'>Subscribe for the video content.</span> |
||||
</a> |
||||
<button class='text-yellow-500 bg-yellow-200 hover:text-yellow-900 hover:bg-yellow-400 outline-0 px-2' onclick='this.parentElement.classList.add("hidden")' aria-label="Close"> |
||||
<Icon icon="close" /> |
||||
</button> |
||||
</div> |
||||
<div |
||||
class='sticky top-0 border-b border-b-yellow-300 z-10 flex h-[37px]' |
||||
youtube-banner |
||||
> |
||||
<a |
||||
href='https://youtube.com/theroadmap?sub_confirmation=1' |
||||
target='_blank' |
||||
class='flex bg-yellow-200 text-center flex-1 items-center justify-center text-sm hover:bg-yellow-300 outline-0' |
||||
> |
||||
<Icon icon='youtube' class='mr-2' /> We now have a YouTube Channel. <span |
||||
class='hidden sm:inline'>Subscribe for the video content.</span |
||||
> |
||||
</a> |
||||
<button |
||||
class='text-yellow-500 bg-yellow-200 hover:text-yellow-900 hover:bg-yellow-400 outline-0 px-2' |
||||
aria-label='Close' |
||||
close-youtube-banner |
||||
> |
||||
<Icon icon='close' /> |
||||
</button> |
||||
</div> |
||||
|
||||
<script> |
||||
document |
||||
.querySelector('[close-youtube-banner]') |
||||
?.addEventListener('click', () => { |
||||
document.querySelector('[youtube-banner]').remove(); |
||||
}); |
||||
</script> |
||||
|
@ -0,0 +1,140 @@ |
||||
--- |
||||
import Answer from '../../components/FAQs/Answer.astro'; |
||||
import FAQs from '../../components/FAQs/FAQs.astro'; |
||||
import Question from '../../components/FAQs/Question.astro'; |
||||
|
||||
const salaryLink = |
||||
'https://www.glassdoor.com/Salaries/united-states-backend-developer-salary-SRCH_IL.0,13_IN1_KO14,31.htm'; |
||||
--- |
||||
|
||||
<FAQs> |
||||
<Question isActive question='What is Backend Development?'> |
||||
<Answer> |
||||
<p class='mb-3'> |
||||
Backend web development is the part of web development that deals with |
||||
the server-side of a web application. This includes creating and |
||||
managing the server-side logic, connecting the application to a |
||||
database, creating server-side APIs, handling user authentication and |
||||
authorization, and processing and responding to user requests. It often |
||||
involves the use of programming languages such as Python, Java, Ruby, |
||||
PHP, JavaScript (Node.js), and .NET languages. |
||||
</p> |
||||
<p> |
||||
A backend developer is responsible for the development of server-side |
||||
components of a web application i.e. working with databases, handling |
||||
requests, creating server-side APIs that can be consumed by frontend |
||||
developers to retrieve and manipulate data, ensuring the scalability of |
||||
the systems i.e. making sure that the backend can handle a high volume |
||||
of traffic and is performant, integrating external services like payment |
||||
gateways, message queues, cloud services, etc. |
||||
</p> |
||||
</Answer> |
||||
</Question> |
||||
|
||||
<Question question='How to become a Backend Developer?'> |
||||
<Answer> |
||||
<p class='mb-3'> |
||||
If you are a complete beginner who is just getting started, you can |
||||
start by learning <span class='bg-yellow-100' |
||||
>a backend programming language</span |
||||
> such as Python, Ruby, Java, Go etc. Once you have got the basic to intermediate |
||||
understanding of the language, learn about <span class='bg-yellow-100' |
||||
>the package manager</span |
||||
> for that language and learn how to install and use external packages into |
||||
your applications. Learn the basics of some <span class='bg-yellow-100' |
||||
>relational database</span |
||||
> e.g. PostgreSQL and learn how to run simple CRUD operations. Optionally, |
||||
you can pick up and learn a <span class='bg-yellow-100' |
||||
>web framework</span |
||||
> for the language of your choice as well. Learn how to build a <span |
||||
class='bg-yellow-100'>simple RESTful API</span |
||||
> and implement simple Authentication/Authorization into it. While you are |
||||
learning all the items mentioned above, don't forget to learn about <span |
||||
class='bg-yellow-100'>Git and GitHub</span |
||||
> as well. |
||||
</p> |
||||
|
||||
<p class='mb-3'> |
||||
After following all the instructions above, you can start applying for |
||||
the entry level backend developer jobs. Also, look at the backend |
||||
developer roadmap above to get an idea about the landscape and see what |
||||
else you are missing. A degree in computer science or related field is |
||||
not always necessary but networking, building a portfolio and actively |
||||
seeking internships, junior developer positions or consulting can help |
||||
to start and advance a career as a backend developer. |
||||
</p> |
||||
|
||||
<p> |
||||
Note: remember to make a lot of projects while you are learning to |
||||
solidify your understanding of the concepts. Also, it's important to |
||||
have the attitude of continuous learning to improve your skills and be |
||||
prepared for the fast-paced technology evolution in the industry. |
||||
</p> |
||||
</Answer> |
||||
</Question> |
||||
<Question question='How long does it take to become a Backend Developer?'> |
||||
<Answer> |
||||
<p class='mb-3'> |
||||
The amount of time it takes to become a backend developer can vary |
||||
depending on several factors, such as your learning pace, previous |
||||
experience and the amount of time you are able to dedicate to learning. |
||||
</p> |
||||
<p> |
||||
If you have a background in computer science or a related field, and |
||||
have experience with programming, you may be able to become a backend |
||||
developer relatively quickly, potentially within a few months. However, |
||||
if you are starting with little or no prior experience or education in |
||||
computer science, it may take longer to develop the necessary skills and |
||||
gain the experience needed to be a proficient backend developer. It |
||||
could take anywhere from 6 months to 2 years. |
||||
</p> |
||||
</Answer> |
||||
</Question> |
||||
<Question question='What are the Backend Developer salaries?'> |
||||
<Answer> |
||||
<p class='mb-3'> |
||||
Backend developer salaries can vary depending on factors such as |
||||
location, experience, and company size. According to data from |
||||
Glassdoor, the average base salary for a backend developer in the United |
||||
States is around $92,000 per year. However, this number can vary greatly |
||||
depending on location, with the highest-paying cities such as San |
||||
Francisco, Seattle and New York having an average salary of $120,000 to |
||||
$135,000 per year. |
||||
</p> |
||||
|
||||
<p class='mb-3'> |
||||
It's important to keep in mind that these are just averages, and |
||||
salaries can vary greatly depending on factors such as experience level, |
||||
specific skills, and the company you work for. With more experience and |
||||
specific skills relevant to the job you are applying for you can expect |
||||
to earn more. |
||||
</p> |
||||
|
||||
<p> |
||||
It is worth looking at a range of resources, including salary surveys, |
||||
and job boards to get a general understanding of the current market in |
||||
your location and experience level. Also try reaching out to other |
||||
professionals in the field and getting an understanding of their own |
||||
experience and salary ranges. |
||||
</p> |
||||
</Answer> |
||||
</Question> |
||||
|
||||
<Question question='Should I learn everything listed on the Backend Roadmap?'> |
||||
<Answer> |
||||
<p class='mb-3'> |
||||
This roadmap contains everything that you might encounter while working |
||||
as a Backend Developer. You may not need everything listed on this |
||||
roadmap to get into the industry; every job is different and most of the |
||||
jobs will require a subset of the items on the roadmap. However, knowing |
||||
what you don't know is as important as knowing things, so you can use |
||||
this roadmap to get an idea of what you are missing as well. |
||||
</p> |
||||
<p> |
||||
If you are a beginner who is just getting started, don't feel |
||||
overwhelmed by looking at this roadmap. Look at the answer to the FAQ |
||||
"How to become a Backend Developer?" |
||||
</p> |
||||
</Answer> |
||||
</Question> |
||||
</FAQs> |
@ -1,18 +1,20 @@ |
||||
# Terminology |
||||
|
||||
Spring Boot is a framework for building Spring-based applications. It provides a set of features and tools to help developers quickly and easily create stand-alone, production-grade Spring-based applications. |
||||
|
||||
Here are a few key terms and concepts that are commonly used when working with Spring Boot: |
||||
|
||||
- Starters: Spring Boot starters are a set of convenient dependency descriptors that you can include in your application to add useful libraries and frameworks to your project. For example, if you want to add Spring MVC to your project, you can include the "spring-boot-starter-web" dependency in your pom.xml file, and Spring Boot will automatically add all of the necessary dependencies to your project. |
||||
|
||||
- Auto-configuration: One of the key features of Spring Boot is its ability to automatically configure your application based on the dependencies that you have included in your project. This can include things like setting up an embedded web server, configuring a database connection, or enabling security features. |
||||
|
||||
- Properties: Spring Boot applications can be configured using a variety of properties. These properties can be defined in a application.properties or application.yml file in the project classpath, and they can be used to configure things like the server port, database connection details, and various other aspects of the application. |
||||
|
||||
- Spring Initializer: Spring Initializer is a web-based tool that allows you to quickly generate a basic structure for a new Spring Boot project, including a pom.xml file with the appropriate dependencies and a simple "Hello, World" application. |
||||
|
||||
For more information visit the following links: |
||||
|
||||
- [Spring Boot - Introduction](https://www.tutorialspoint.com/spring_boot/spring_boot_introduction.htm) |
||||
- [Spring Boot Tutorial](https://www.digitalocean.com/community/tutorials/spring-boot-tutorial) |
||||
Spring Core is the foundation of the Spring Framework, which provides a comprehensive programming and configuration model for Java-based applications. Here are some key terms and concepts related to Spring Core: |
||||
|
||||
- Beans: In Spring, a "bean" is a Java object that is managed by the Spring container. Beans are typically defined using configuration metadata, which can be specified in XML, Java annotations, or Java code. |
||||
- Inversion of Control (IoC): One of the main principles of Spring is Inversion of Control (IoC), which means that the Spring container is responsible for managing the lifecycle of beans and injecting their dependencies. |
||||
- Dependency Injection (DI): Spring uses Dependency Injection (DI) to manage the dependencies between beans. In DI, an object's dependencies are provided to it by the container, rather than the object creating or looking up its own dependencies. |
||||
- Container: The Spring container is the core part of the Spring Framework, which creates and manages beans and their dependencies. |
||||
- ApplicationContext: An ApplicationContext is an implementation of the Spring container. It is responsible for loading and managing the configuration metadata and creating the beans defined in that metadata. |
||||
- Aspect-Oriented Programming (AOP): Spring supports Aspect-Oriented Programming (AOP), which allows you to separate cross-cutting concerns, such as logging or security, from the business logic of your application. |
||||
- Events: Spring provides an event model that allows beans to send and receive events. This is used to decouple the beans from each other, making the application more loosely coupled. |
||||
- ApplicationEvent and listener: Spring support publish subscribe model for event handling, ApplicationEvent defines event object, and the listener is a class that implements ApplicationListener interface, listening for the specific event and take the necessary action. |
||||
- Data Access: Spring provides a consistent, high-level abstraction for data access using various frameworks like JDBC, Hibernate, JPA. |
||||
- Transactions: Spring provides a flexible, consistent and easy way to declaratively manage transactions with different underlying technologies such as JPA, JDBC, and Hibernate. |
||||
- Task Execution and Scheduling: Spring provides a TaskExecutor and TaskScheduler, providing a convenient way to run tasks concurrently, on a scheduled basis or asynchronously. |
||||
|
||||
This list is not exhaustive, it covers common terms and concepts used. Visit the following links to learn more about Spring: |
||||
|
||||
- [Spring Boot - Official Website](https://spring.io/projects/spring-boot) |
||||
- [Spring Boot - Starter Guide](https://spring.io/quickstart) |
Loading…
Reference in new issue