When starting a new web project where JavaScript will be used, often the first thing we do is set up build and developer tooling. For example, Vite, which is a popular these days. You might not be aware that complicated build tooling it not needed for all JavaScript (web) projects. In fact, it is now easier to go without than ever before as I will show in this article.
Create a new project with an index.html file.
<p>Hello world</p>
If you are using VS Code, install the Live Preview extension. Run it. This is a simple file server with live reload. You can use any file server, Python comes with one built in:
python3 -m http.server
I like Live Preview, because it automatically refreshes the page after making changes to a file.
You should now be able to access your index.html file from the browser and see "Hello world".
Next, create an index.js file:
console.log("Hello world"); export {};
Include it in your index.html:
<script type="module" src="./index.js"></script>
Open the developer console in your browser. If you see "Hello world", you know that it is loading properly.
Browsers support ECMAScript modules now. You can import other files for their side effects:
import "./some-other-script.js";
or for their exports
import { add, multiply } "./my-math-lib.js";
Pretty cool right? Refer to the MDN guide above for more information.
Packages
You probably don't want to re-invent the wheel, so your project will probably use some third-party packages. That doesn't mean you now need to start using a package manager.
Say we want to use superstruct for data validation. We can can not just load modules from our own (local) file server, but from any URL. esm.sh conveniently provides modules for almost all packages available on npm.
When you visit https://esm.sh/superstruct you can see that you are re-directed to the latest version. You can include this package as follows in your code:
import { assert } from "https://esm.sh/superstruct";
If you want to be on the safe side, you can pin versions.
Types
I don't know about you, but TypeScript spoiled me (and made me lazy). Writing plain JavaScript without help from the type checker feels like writing over a tightrope. Luckily, we don't have to forgo type checking either.
It is time to bust out npm (even though we won't ship any code it provides).
npm init --yes npm install typescript
You can use the TypeScript compiler on JavaScript code just fine! There is first-class support for it. Create a jsconfig.json:
{ "compilerOptions": { "strict": true, "checkJs": true, "allowJs": true, "noImplicitAny": true, "lib": ["ES2022", "DOM"], "module": "ES2022", "target": "ES2022" }, "include": ["**/*.js"], "exclude": ["node_modules"] }
Now run
npm run tsc --watch -p jsconfig.json
and make a type error in your code. The TypeScript compiler should complain:
/** @type {number} **/ const num = "hello";
By the way, the comment you see above is JSDoc. You can annotate your JavaScript with types this way. While it is a little bit more verbose than using TypeScript, and you get used to it pretty quickly. It is also very powerful, as long as you are not writing crazy types (which you should not for most projects) you should be fine.
If you do need a complicated type (helper), you can always add some TypeScript in a .d.ts file.
Is JSDoc just a stepping stone for people stuck with large JavaScript projects to be able to gradually migrate gradually to TypeScript? I don't think so! The TypeScript team also continues to add great features to JSDoc + TypeScript, such as in the upcoming TypeScript release. Auto-completion also works great in VS Code.
Import maps
We learned how to add external packages to our project without a build tool. However, if you split your code in a lot of modules, writing out the complete URL over and over again might be a bit verbose.
We can add an import map to the head section of our index.html:
<script type="importmap"> { "imports": { "superstruct": "https://esm.sh/superstruct@1.0.4" } } </script>
Now we can simply import this package with
import {} from "superstruct"
Like a 'normal' project. Another benefit is that completion and recognition of types will work as expected if you install the package locally.
npm install --save-dev superstruct
Note that the version in your node_modules directory will not be used. You can remove it, and your project will continue to run.
A trick I like to use is to add:
"cdn/": "https://esm.sh/",
To my import map. Then any project available through esm.sh can be used by simply importing it. E.g.:
import Peer from "cdn/peerjs";
If you want to pull types from node_modules for development for this type of import as well, you need to add the following to the compilerOptions of your jsconfig.json:
"paths": { "cdn/*": ["./node_modules/*", "./node_modules/@types/*"] },
Deployment
To deploy your project, copy all the files to a static file host and you are done! If you have ever worked on a legacy JavaScript project, you know the pain of getting build tooling updated that is not even 1-2 years old. Your will not suffer the same fate with this project setup.
Testing
If your JavaScript does not depend on browser APIs, you could just use the test runner that comes bundled with Node.js. But why not write your own test runner that runs right in the browser?
/** @type {[string, () => Promise<void> | void][]} */ const tests = []; /** * * @param {string} description * @param {() => Promise<void> | void} testFunc */ export async function test(description, testFunc) { tests.push([description, testFunc]); } export async function runAllTests() { const main = document.querySelector("main"); if (!(main instanceof HTMLElement)) throw new Error(); main.innerHTML = ""; for (const [description, testFunc] of tests) { const newSpan = document.createElement("p"); try { await testFunc(); newSpan.textContent = `✅ ${description}`; } catch (err) { const errorMessage = err instanceof Error && err.message ? ` - ${err.message}` : ""; newSpan.textContent = `❌ ${description}${errorMessage}`; } main.appendChild(newSpan); } } /** * @param {any} val */ export function assert(val, message = "") { if (!val) throw new Error(message); } </void></void>
Now create a file example.test.js.
import { test, assert } from "@/test.js"; test("1+1", () => { assert(1 + 1 === 2); });
And a file where you import all your tests:
import "./example.test.js"; console.log("This should only show up when running tests");
Run this on page load:
await import("@/test/index.js"); // file that imports all tests (await import("@/test.js")).runAllTests();
And you got a perfect TDD setup. To run only a section of the tests you can comment out a few .test.js import, but test execution speed should only start to become a problem when you have accumulated a lot of tests.
Benefits
Why would you do this? Well, using fewer layers of abstraction makes your project easier to debug. There is also the credo to "use the platform". The skills you learn will transfer better to other projects. Another advantage is, when you return to a project built like this in 10 years, it will still just work and you don't need to do archeology to try to revive a build tool that has been defunct for 8 years. An experience many web developers that worked on legacy projects will be familiar with.
See plainvanillaweb.com for some more ideas.
The above is the detailed content of Web Development Without (Build) Tooling. For more information, please follow other related articles on the PHP Chinese website!

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Zend Studio 13.0.1
Powerful PHP integrated development environment

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),
