Viimeisen vuoden aikana olen kompuroinut, kokeillut, rikkonut asioita ja vähitellen modernisoinut tämän blogin etuosan rakennusputkea. Tämä ei ollut mikään mestarisuunnitelma, joka toteutettiin virheettömästi – se oli yritys ja virhe, paljon virheitä ja itsepäistä sinnikkyyttä, jonka taustalla oli selkeä visio siitä, mitä halusin saavuttaa.
En ole etunojaguru enkä Webpack-velho. Olen .NET-kehittäjä, joka turhautui CDN-pohjaisten riippuvuussuhteiden rajoitteisiin ja päätti, että on oltava parempi tapa. Tässä artikkelissa dokumentoidaan sotkuista, iteratiivista matkaa yksinkertaisesta <script> Tagit, jotka osoittavat, että unpkg on nykyaikainen niputusputki, joka todella toimii.
Tein matkan varrella paljon virheitä (jotka dokumentoin), käytin tunteja salamyhkäisten Webpack-virheiden vianetsintään ja luultavasti asensin ne uudelleen node_modules Mutta sinnikkyys kannatti, ja opin valtavasti pelkän päättäväisyyden kautta.
Jos olet .NET-kehittäjä, joka tuijottaa Webpack-asetustiedostoja, ihmettelet, mihin olet joutunut - tämä artikkeli on sinua varten.
Olen vanha nettiperformanssin kahjo, ja alkuaikoina, kun valitsin ensimmäisen sivuston, jonka rakensin rahasta (se ei ollut pornon taustaosa Perlissä...juttu toiseen kertaan), se oli Lumiolosuhteet-sivusto, joka kehrättiin pois automaattisesta puhelinlinjasta.
Siihen aikaan huoli oli aivan toinen. JavaScript oli käytännössä tuntematon. Uskon, että jopa divs oli RARE (niinä päivinä IE oli div Ja Netscape oli layer) ja olisit onnekas, jos käyttäjilläsi olisi 56K-yhteys. Niinpä opin optimoimaan (jopa kaapeloidut kuvataustat valikkoesineille) jne....
Myöhemmin Microsoftilla työskentelin jopa Web Forms -sivuston automaattisen kuvan sprite-työkalun parissa - se oli mahtava: se keräsi pieniä kuvia sivulta, loi CSS:n ja sprite-kuvan automaattisesti. Mutta valitettavasti, kuten Microsoftin aikani, ei ollut tarkoituskaan.
Lyhyesti sanottuna se on pakkomielle, että olen kantanut koko urani. Kukaan ei pidä hitaasta nettisivustosta!
Ollakseni reiluCDN:t eivät ole luonnostaan pahoja.
Täydet tiedotTämä blogi on tarkoituksella ylikehitetty. tarve Kaikki tämä monimutkaisuus. Mutta kun rakennan sen tällä tavalla, opettelen modernin frontend-työkalun kunnolla ja, ratkaisevasti, sain jotain todellista kirjoitettavaa ja opetettavaa. Joskus paras tapa oppia on rakentaa jotain hieman naurettavaa ja dokumentoida matka.
Aluksi lähestymistapani oli yksinkertainen:
<!-- Old CDN-based approach -->
<script src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
Vaikka tämä toimii, sillä on useita haittoja, joista tuli yhä turhauttavampia:
Joten halusin kontrolloida... kontrolloida juuri sitä, mitä sivustoni käytti ja tarvitsi toimiakseni. Halusin niputtaa vain sen, mitä tarvitsin, varmistaa luotettavan latausjärjestyksen ja optimoida suorituskyvyn. Tämä tarkoitti siirtymistä pois CDN-levyiltä ja kohti niputtamista.
Ne on yksinkertaisempi perustaa, ja HTTP/2:n ja HTTP/3:n multipleksoinnin myötä moninkertainen pyyntö on paljon vähemmän kriittinen kuin aiemmin. Monissa projekteissa, erityisesti pienissä tai prototyypeissä, CDN:t ovat edelleen täysin järkevä valinta, mutta tuotantopaikalla, jossa halusin valvontaa, luotettavuutta ja optimointia, niputtaminen oli järkevämpää.
Nykyinen settini yhdistää kaikki Javascript-riippuvuudet Webpackin kautta ja käsittelee CSS:ää PostCSS:n kautta.
Ennen kuin sukeltan yksityiskohtiin, minun pitäisi puhua huoneessa olevalle norsulle: miksi käytän Webpackia, kun Vite, Rollup, esbuild ja muut modernit nippukauppiaat ovat olemassa?
Rehellinen vastaus on yksinkertainen: Tunsin jo Webpackin.
Olin käyttänyt Webpackia laajasti opettaessani verkkokehityksen aloituskurssiani, ja se oli työkalu, jonka ymmärsin. Kun päätin modernisoida tämän blogin rakennusputken, edessäni oli jo jyrkkä oppimiskäyrä, jossa ymmärsin puiden ravistelua, koodinjakoa, moduulijärjestelmiä, PostCSS-putkistoja ja miten tämä kaikki yhdistettiin ASP.NET Coreen.
Se on yleensä hyvä käytäntö, kun työstetään projekteja, rajataan "uusi" "hallittavissa olevaan". Se on tapa, jolla epävarmuutta on helpompi rajoittaa.
"Opettele täysin uusi rakennustyökalu" sen päälle vaikutti tarpeettomalta. Webpack toimii. Se on kypsä. Siinä on erinomainen dokumentointi ja valtava ekosysteemi. käsitteet Nykyaikaisesta niputtamisesta eikä tietyn työkalun omalaatuisuudesta.
Onko Vite nopeampi? Viten kehityspalvelin alkuperäisillä ES-moduuleilla ja eskonstruktiolla on huomattavasti nopeampi kuin Webpack. Suurissa projekteissa, joissa on satoja moduuleja, ero on dramaattinen.
Pitäisikö sinun käyttää Viteä uuteen projektiin? Vite on todennäköisesti parempi valinta, jos aloittaa puhtaalta pöydältä ilman olemassa olevaa Webpack-tietoa. Se on nopeampi, yksinkertaisempi konfiguroida ja edustaa modernia lähestymistapaa etupään työkaluihin.
Kadunko Webpackin käyttöä? Ei lainkaan. Se vei minut sinne, missä minun pitikin olla. Opetukseni niputtamisesta, koodien jakamisesta ja optimoinnista ovat siirrettävissä mihin tahansa rakennustyökaluun. Tämän blogin mittakaavan vuoksi Webpackin ja Viten suoritusero on mitätön – puhutaan millisekunneista kehityksen korjausajoissa.
Se on keskeinen osa sitä, miten rakennan tavaraa; aloita siitä, mikä on helppoa ja rakenna siltä pohjalta.
Laajempi opetus tässä on se, että edistys voittaa täydellisyydenOlisin voinut viikkokausia tutkia "parasta" nippua, vertailla vertailutietoja, lukea vertailusanoja ja tuskailla päätöstä. Sen sijaan valitsin työkalun, jonka tiesin, sain sen toimimaan ja jatkoin eteenpäin. Tuo pragmatismi piti minut laivassa eikä loputtomasti keskustelemassa.
Ehkä jonain päivänä voisin muuttaa Vitelle. Ehkä en. Joka tapauksessa tässä blogissa on moderni, optimoitu rakennusputki, joka toimii luotettavasti, ja juuri sillä on merkitystä.
Erytropoietiini package.json Nyt minulla on kaksi erillistä riippuvuusryhmää. Tämä rakenne vaati useita yrityksiä saada asiat kuntoon – aluksi Nuget ja npm ovat samanlaisia, mutta nppm on paljon vähemmän ystävällinen, kun siihen lisätään pacakgeja.
{
"dependencies": {
//NOTE - This is a pre-release of these enhancements, the 1.0.0 release is OUT NOW!
"@mostlylucid/mermaid-enhancements": "^1.0.0-alpha0",
"alpinejs": "^3.14.1",
"codemirror": "5.65.13",
"core-js": "^3.39.0",
"easymde": "2.20.0",
"flatpickr": "^4.6.13",
"highlight.js": "^11.10.0",
"highlightjs-cshtml-razor": "^2.1.1",
"html-to-image": "^1.11.13",
"htmx.org": "^2.0.1",
"mermaid": "^11.0.2",
"regenerator-runtime": "^0.14.1",
"svg-pan-zoom": "^3.6.2"
},
//These are just used for build; not needed to RUN the app so we have a separate place for 'em
"devDependencies": {
"@babel/core": "7.26.9",
"@babel/preset-env": "7.26.9",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.12",
"autoprefixer": "10.4.21",
"babel-loader": "10.0.0",
"cpx": "1.5.0",
"css-loader": "7.1.2",
"cssnano": "7.0.6",
"daisyui": "^4.12.10",
"mini-css-extract-plugin": "^2.9.4",
"npm-run-all": "4.1.5",
"postcss": "8.5.3",
"postcss-cli": "11.0.1",
"postcss-import": "^16.1.0",
"rimraf": "6.0.1",
"style-loader": "4.0.0",
"tailwindcss": "3.4.17",
"terser-webpack-plugin": "^5.3.10",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
}
}
Riippuvuussuhteet ovatko kirjastot tarpeen ajon aikana (Alpine.js, HTMX, EasyMDE jne.), kun taas devDependiteetit ovat rakennustyökaluja (Webpack, Babel, PostCSS-prosessorit jne.).
Erytropoietiini package.json käsikirjoitukset ovat kehittyneet merkittävästi:
{
"scripts": {
"clean": "rimraf ./.tmp ./wwwroot/css/dist ./wwwroot/js/dist",
"copy:static": "cpx \"src/css/{raleway,easymde-overrides}.css\" \"wwwroot/css/dist\"",
"copy:highlight": "cpx \"src/css/highlight/*.min.css\" \"wwwroot/css/highlight\"",
"copy:all": "npm-run-all --parallel copy:static copy:highlight",
"copy:watch": "cpx \"src/css/{raleway,easymde-overrides}.css\" \"wwwroot/css/dist\" --watch & cpx \"src/css/highlight/*.min.css\" \"wwwroot/css/highlight\" --watch",
"tw:dev": "postcss ./src/css/main.css -o ./wwwroot/css/dist/main.css",
"tw:prod": "postcss ./src/css/main.css -o ./wwwroot/css/dist/main.css --no-map --verbose",
"tw:watch": "postcss ./src/css/main.css -o ./wwwroot/css/dist/main.css --watch",
"js:dev": "webpack --env development",
"js:prod": "webpack --mode production",
"js:watch": "webpack watch --mode development",
"dev": "npm-run-all clean --parallel copy:all tw:dev js:dev",
"watch": "npm-run-all clean copy:all --parallel copy:watch tw:watch js:watch",
"build": "npm-run-all clean copy:all --parallel tw:prod js:prod"
}
}
Tämä asetus erottaa toisistaan seuraavat seikat:
rimrafErytropoietiini npm-run-all Paketti mahdollistaa rinnakkaistoteutuksen nopeammille rakennuksille.
Voit asettaa npm run build Automatisoiminen paikallisen rakentamisen aikana, mutta se on hieman hankalaa CI:lle (se täytyy varmistaa, että se on toimintakyvytön jne.).
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<SpaRoot>ClientApp\</SpaRoot>
</PropertyGroup>
<!-- Run npm install only when package.json changes -->
<Target Name="NpmInstall" Inputs="$(SpaRoot)package.json" Outputs="$(SpaRoot)node_modules" BeforeTargets="Build">
<Message Importance="high" Text="Running npm install in $(SpaRoot)" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm ci" />
</Target>
<!-- Run npm build before the .NET build -->
<Target Name="NpmBuild" DependsOnTargets="NpmInstall" BeforeTargets="Build">
<Message Importance="high" Text="Running npm run build in $(SpaRoot)" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
</Target>
</Project>
Jos haluat vain lisätä tämän csproj... Voit jopa sanoa vain ajaa aikana debug' jne....mutta pidän sitä sotkuisena. Haluan vain manuaalisesti ajaa sen. Joten npm run watch tekee juuri niin, kun mikä tahansa css / js-tiedosto muuttuu, se automaattisesti pyörittää rakennelmaa.
HUOMAUTUS: JS-maailmassa he melkein käyttävät kuumaladattuja dev-juoksuja, mikä on aika ovelaa ja saa tavallaan vihaamaan ASP.NET Coren heikkoa yritystä.
Webpack-kokoonpano on paikka, jossa taika tapahtuu – ja jossa käytin suurimman osan ajastani vianetsintään. Tämä ei syntynyt täysin. Se on tulosta lukemattomista iteroinneista, Stack Overflow -hauista ja lukemasta Webpack-dokumentaatiosta kello 2.00 yrittäen ymmärtää, miksi rakennukseni tuotti 47 kappaletta tiedostoja.
Tässä on nykyinen asetus (alkaen webpack.config.js) yksityiskohtaisilla selvityksillä siitä, mitä kukin osa tekee ja miksi se on siellä:
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
mode: isProduction ? 'production' : 'development',
entry: {
main: './src/js/main.js',
},
output: {
filename: '[name].js',
chunkFilename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'wwwroot/js/dist'),
publicPath: '/js/dist/',
module: true,
clean: true,
},
experiments: {
outputModule: true,
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: '> 0.25%, not dead',
modules: false,
useBuiltIns: 'usage',
corejs: 3,
}],
],
},
},
},
],
},
resolve: {
extensions: ['.js', '.mjs'],
alias: {
'@mostlylucid/mermaid-enhancements$': path.resolve(__dirname, 'node_modules/@mostlylucid/mermaid-enhancements/dist/index.min.js')
}
},
optimization: {
splitChunks: {
chunks: 'all',
minSize: 20000,
maxSize: 100000,
name: false,
},
runtimeChunk: {
name: 'runtime',
},
minimize: isProduction,
minimizer: isProduction ? [
new TerserPlugin({
terserOptions: {
ecma: 2020,
compress: {
drop_console: true,
passes: 3,
toplevel: true,
pure_funcs: ['console.info', 'console.debug'],
},
mangle: {
toplevel: true,
},
format: {
comments: false,
},
},
extractComments: true,
}),
] : [],
},
devtool: isProduction ? false : 'eval-source-map',
performance: {
hints: isProduction ? 'warning' : false,
}
};
};
optimization: {
splitChunks: {
chunks: 'all',
minSize: 20000,
maxSize: 100000,
name: false,
},
runtimeChunk: {
name: 'runtime',
},
}
Tämä asetus jakaa koodisi automaattisesti pienempiin osiin:
Käytännössä tämä luo useita tiedostoja wwwroot/js/dist/:
main.js - Hakemuksen hakupisteruntime.js - Webpack-moduulin latauslogiikka[vendor].[contenthash].js - Automaattisesti jaettuja myyjän palasia{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: '> 0.25%, not dead',
modules: false,
useBuiltIns: 'usage',
corejs: 3,
}],
],
},
},
}
Baabelin transpiles modern JavaScript tukee vanhempia selaimia:
Tämä tarkoittaa, että voin kirjoittaa modernin JavaScriptin (async/await, optional chaining, nullish collessaging) säilyttäen samalla laajan selaintuen.
minimizer: isProduction ? [
new TerserPlugin({
terserOptions: {
ecma: 2020,
compress: {
drop_console: true,
passes: 3,
toplevel: true,
pure_funcs: ['console.info', 'console.debug'],
},
mangle: {
toplevel: true,
},
format: {
comments: false,
},
},
extractComments: true,
}),
] : []
Terser minimoi tuotantorakennuksia aggressiivisesti:
console.log() lausunnotTässä blogissa tämä tyypillisesti pienentää JavaScript-nippukokoja 60-70 prosentilla verrattuna minimoimattomaan koodiin.
Perätuuli CSS:ää käsitellään PostCSS:n kautta useilla liitännäisillä. Tämä asetus (alkaen postcss.config.js) on armollisen yksinkertainen verrattuna Webpackiin:
// postcss.config.js
module.exports = {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {},
cssnano: { preset: 'default' }
}
}
Putkisto toimii seuraavasti:
@import lausuntoja CSS-tiedostoissaErytropoietiini tailwind.config.js Tiedosto määrittelee, mistä Tailwindin tulisi etsiä luokan nimiä. content Oikeat polut olivat kriittisiä – missaa polku ja Tailwind ei luo kursseja noille tiedostoille:
module.exports = {
content: ["./Views/**/*.cshtml", "./EmailSubscription/**/*.cshtml"],
safelist: ["dark", "light"],
darkMode: "class",
theme: {
fontFamily: {
body: ["Raleway", "sans-serif"],
},
extend: {
colors: {
"custom-light-bg": "#ffffff",
"custom-dark-bg": "#1d232a",
primary: "#072344",
secondary: "#00aaa1",
// ... more custom colours
},
},
},
plugins: [
require("@tailwindcss/aspect-ratio"),
require("@tailwindcss/typography"),
require("daisyui"),
],
};
Tärkeimmät ominaisuudet:
.cshtml luokannimien tiedostot (mukaan lukien Razorin näkymät ja sähköpostimallit)Sen vuoksi lopullinen CSS-tiedosto on paljon pienempi kuin koko Tailwind-kirjasto.
Erytropoietiini main.js Tämä tiedosto tuo ja alustaa kaikki riippuvuudet, ja se on kasvanut orgaanisesti, kun olen lisännyt ominaisuuksia blogiin:
// src/js/main.js
import hljsRazor from "highlightjs-cshtml-razor";
import mermaid from "mermaid";
import Alpine from 'alpinejs';
import htmx from "htmx.org";
import hljs from "highlight.js";
import EasyMDE from "easymde";
import 'easymde/dist/easymde.min.css';
import flatpickr from "flatpickr";
import 'flatpickr/dist/flatpickr.min.css';
// Expose libraries globally for Razor views
window.Alpine = Alpine;
window.hljs = hljs;
window.htmx = htmx;
window.mermaid = mermaid;
window.EasyMDE = EasyMDE;
window.flatpickr = flatpickr;
// Import custom modules
import { typeahead } from "./typeahead";
import { submitTranslation, viewTranslation } from "./translations";
import { codeeditor } from "./simplemde_editor";
import { globalSetup } from "./global";
import { comments } from "./comments";
// Attach to namespace
window.mostlylucid = window.mostlylucid || {};
window.mostlylucid.typeahead = typeahead;
window.mostlylucid.comments = comments();
window.mostlylucid.translations = {
submitTranslation: submitTranslation,
viewTranslation: viewTranslation
};
// Initialise Alpine
Alpine.start();
Tästä lähestymistavasta on useita etuja:
windowSisään _Layout.cshtmlNyt viittaan vain niputettuihin omaisuuseriin:
<head>
<link href="/css/dist/main.css" asp-append-version="true" rel="stylesheet" />
</head>
<body>
<!-- Content -->
<script src="~/js/dist/main.js" type="module" asp-append-version="true"></script>
</body>
Huomautusta täsmennän module Kertoaksesi selaimelle, minkä tyyppinen JS-tiedosto tämä on & asp-append-version Näppärä pieni ASP.NET-tunnisteavustin, joka liittää hashed-version tiedostojen sisällöstä kyselyyn; tehokkaasti välimuistin syötön, kun tiedosto muuttuu.
Ainoat jäljellä olevat CDN-riippuvuudet ovat:
Näin koko rakennusprosessi siirtyy lähdetiedostoista tuotanto-omaisuuteen:
graph TD
A[Source Files] --> B[npm run build]
B --> C[Clean Task]
C --> D[rimraf wwwroot/css/dist wwwroot/js/dist]
B --> E[Copy Task]
E --> F[cpx: Copy static CSS files]
F --> G[wwwroot/css/dist/raleway.css]
F --> H[wwwroot/css/dist/easymde-overrides.css]
B --> I[Tailwind Task]
I --> J[PostCSS Pipeline]
J --> K[postcss-import]
K --> L[Tailwind CSS]
L --> M[Autoprefixer]
M --> N[cssnano]
N --> O[wwwroot/css/dist/main.css]
B --> P[Webpack Task]
P --> Q[Entry: src/js/main.js]
Q --> R[Babel Transpilation]
R --> S[Module Resolution]
S --> T[Tree Shaking]
T --> U[Code Splitting]
U --> V[Terser Minification]
V --> W[wwwroot/js/dist/main.js]
V --> X[wwwroot/js/dist/runtime.js]
V --> Y[wwwroot/js/dist/vendor chunks]
O --> Z[ASP.NET Core Static Files]
W --> Z
X --> Z
Y --> Z
G --> Z
H --> Z
Z --> AA[Browser]
style A stroke:#0ea5e9,stroke-width:3px
style Z stroke:#f59e0b,stroke-width:3px
style AA stroke:#10b981,stroke-width:3px
Se näyttää aika monimutkaiselta, mutta sitä WebPack tekee, se käsittelee suurimman osan tästä itse (monimutkaisella tavalla, jota Viten kaltaiset eivät tarvitse, mutta.)
Ei oikeastaan piste, mutta nyt se on kuin ehdoton luoti. Cloudflaren "Rocket Loader" (joka kolauttaa sivuja jonkin verran) voi silti aiheuttaa ongelmia, mutta se on TIGHT.
Suorituskyvyn lisäksi nykyaikainen rakennusputki parantaa merkittävästi kehitystyön sujuvuutta:
Webpackin avulla yhteenliittäminen mahdollistaa oikean Javascript-moduulin resoluution, mikä tarkoittaa:
KUN rakennus katkeaa npm run watch) Tiedän, että yhdessä (harvan mutta kasvavan) JS-yksikön testien kanssa se tarkoittaa tiukempia palautesilmukoita.
Kehityksen aikana npm run watch mahdollistaa lähes välittömän palautteen:
npm run watch
Tämä pyörittää Webpackia kellotilassa, uudelleenrakentamalla vain vaihdettuja moduuleja:
npm:n lukitustiedosto (package-lock.json) varmistaa johdonmukaisen rakentamisen eri ympäristöissä:
npm ci # Clean install from lock file
Tämä takaa samat riippuvuusversiot kehitys-, CI/CD- ja tuotantoympäristöissä.
Niitä kutsutaan JS-maailmassa "pinnaksi", jossa riippuvuudet ovat kiveen hakattuja. Voit pärjätä ilman pakettilukkoa, mutta sitten olet riippuvainen packge-kirjoittajista; usein HUNDREDS on erilainen ihminen, joka ei pilaa pientä julkaisua..s
Järjestetyt npm-kirjoitukset helpottavat yhteisiä tehtäviä:
npm run dev # One-time development build
npm run watch # Continuous development builds
npm run build # Production build with optimisations
npm run clean # Remove build artefacts
Jotkin kirjastot tarvitsevat maailmanlaajuista altistusta käyttääkseen Razor-näkymiä tai inline-skriptejä:
// Make library available globally
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
Sitten sisään .cshtml tiedostot:
<div x-data="{ open: false }">
<!-- Alpine.js works because it's on window -->
</div>
Joihinkin kirjastoihin kuuluu tuontia kaipaava CSS:
import EasyMDE from "easymde";
import 'easymde/dist/easymde.min.css'; // Imported CSS is processed by Webpack
Webpack's css-loader sekä style-loader käsitellä näitä tuontituotteita:
<style> tunnisteet tai erilliset CSS-tiedostotJos kirjastoja tarvitaan vain tietyillä sivuilla, käytä dynaamista tuontia:
// Only load Mermaid when needed
async function initMermaid() {
const mermaid = await import('mermaid');
mermaid.default.initialize({ startOnLoad: true });
}
// Call when needed
if (document.querySelector('.mermaid')) {
initMermaid();
}
Webpack jakaa automaattisesti koodin jakaen dynaamisen tuonnin erillisiksi kappaleiksi, jotka ladataan tilauksesta.
Osa vanhoista kirjastoista käyttää CommonJS:ää ES6-moduulien sijaan:
// CommonJS require syntax
const hljs = require('highlight.js');
// Or use dynamic import
import('highlight.js').then(hljs => {
// Use hljs
});
Webpack käsittelee molemmat moduulijärjestelmät läpinäkyvästi ja muuntaa tarvittaessa CommonJS:n ES6:ksi.
Varmista devtool on konfiguroitu webpack.config.js:
devtool: isProduction ? false : 'eval-source-map',
Tämä tuottaa lähdekarttoja helpommaksi vianetsintää varten.
Jos Tailwind poistaa käyttämäsi kurssit, tarkista content kokoonpano:
// tailwind.config.js
module.exports = {
content: [
'./Views/**/*.cshtml',
'./Components/**/*.cshtml',
// Add any other paths where classes are used
],
}
Vaihtoehtoisesti on käytettävä safelist Dynaamiset luokat:
safelist: [
'bg-blue-500',
'text-red-600',
{
pattern: /bg-(red|green|blue)-(400|500|600)/,
}
]
Jos Webpack ei pysty ratkaisemaan moduulia, tarkista:
./ tai ../.mjs Kohtiin resolve.extensions tarvittaessaresolve.alias monimutkaisille poluilleresolve: {
extensions: ['.js', '.mjs', '.json'],
alias: {
'@components': path.resolve(__dirname, 'src/js/components/'),
}
}
Jos rakennuksista tulee hitaita:
thread-loader monisäikeisen transpilaation osalta// Enable Webpack caching
cache: {
type: 'filesystem',
},
Anna minun jakaa joitakin virheitä, joita tein tämän matkan aikana, jotta voit välttää ne:
Ensimmäinen yritykseni oli repiä pois kaikki CDN-viitteet yhdellä kertaa ja yrittää niputtaa kaiken Webpackin läpi. Rakennus hajosi näyttävästi. Opin, että asteittainen muuttoliike on ystäväsi – siirrä kirjasto kerrallaan, testaa perusteellisesti ja siirry seuraavaan.
Tuhlasin tunteja yrittäessäni selvittää, miksi tietyt kirjastot eivät lataisi.require()) ja ES6-moduuleita (import) ymmärtämättä, miten Webpack käsittelee niitä, johtaa salamyhkäisiin virheisiin. experiments: { outputModule: true } Konfiguraatio ei ollut alkuperäisessä kokoonpanossani, enkä ymmärtänyt, miksi moduulejani ei ladattu.
Ratkaisu syntyi lukemalla GitHub-numeroita Webpackin arkistosta keskiyöllä.
Yhdessä vaiheessa konfiguraationi tuotti paloja kaikkeen. minSize: 10000 (10KB), joka tarkoitti, että Webpack loi erilliset tiedostot pieniä aputoimintoja varten. Ylikorjattu ja meni 2MB:lle... Sivukuormasta tuli 50+ pienen palan vesiputous tai se roikkui odottamassa valtavia kappaleita ladattavaksi. Opin, että koodin jakaminen on hyvä, mutta tarvitset järkeviä raja-arvoja. Siksi nykyinen konfiguraationi käyttää sitä. minSize: 20000 (20 KB).
.mjs LaajennusJotkin npm-paketit jakavat ES6-moduuleja .mjs Laajennus. Webpack ei ratkaise näitä oletuksena. Vietin häkellyttävän pitkään vianetsintää, miksi @mostlring I needed to add .mjstoPäättäkää.laajennukset.
Helppo ratkaisu, kun sen tietää, mutta sen selvittäminen vei aikaa.
Varhaisrakennukset kestivät 30-60 sekuntia, koska en ollut ottanut käyttöön Webpackin tiedostojärjestelmää. Kun lisäsin välimuistin, rekonstruktioajat laskivat 2-3 sekuntiin. Tämä oli kehitystyön muuttaja, mutta minulta kesti viikkoja löytää se.
Suosikki vianetsintäkokemukseni: CSS-kurssit, jotka toimivat hyvin kehityksessä, katosivat yhtäkkiä tuotannossa. Tailwind puhdisti niitä, koska ne syntyivät dynaamisesti JavaScriptissa. Ratkaisuna oli safelist Konfiguraatio, mutta vasta sen jälkeen, kun olin hukannut tunteja miettiessäni, olenko tulossa hulluksi.
I MYÖS (esimerkiksi mostlylucid.pagingtaghelper Project) käytä "Dummy Blocksia", jossa yksinkertaistan Tailwind-konfigurointiani vain piilottamalla lohkon.
<!--
Preserve Tailwind & DaisyUI classes used in embedded pager views.
Without this, TailwindCSS tree-shaking removes classes from the embedded library views.
-->
<span class="hidden
btn btn-sm btn-active btn-disabled join join-item badge badge-sm select select-bordered select-sm label label-text
px-3 py-2 py-1 text-sm font-medium border rounded whitespace-nowrap cursor-not-allowed
text-gray-700 text-gray-600 text-gray-400 text-white bg-white bg-gray-100 bg-blue-600 border-gray-300 border-blue-600
hover:bg-gray-50 hover:bg-blue-700
dark:bg-gray-800 dark:bg-gray-700 dark:bg-blue-500 dark:text-gray-300 dark:text-gray-500 dark:text-gray-200
dark:border-gray-600 dark:border-blue-500 dark:hover:bg-gray-700 dark:hover:bg-blue-600">
</span>
Kun Tailwind rakentaa sen skannataan cshtml-tiedostoja luokille; jos se ei näe niitä, se poistaa ne. Jos tämä piilotettu lohko varmistaa, että se näkee tarvitsemani luokat, vaikka niitä käytettäisiin vain sulautetuissa kirjaston näkymissä. JS-kehittäjät yleensä myös skannattavat JS/TS-tiedostoja, jotta he voivat käyttää CSS-tyylejä, joita Tailwind muuten ei huomaa.
module.exports = {
content: ["./Views/**/*.cshtml", "./EmailSubscription/**/*.cshtml"],
-//^^^^ This is what Tailwing knows where to look for classes duritng the tree Shake.
+//^^^^ This is what Tailwind knows where to look for classes during the tree-shake.
...
future: {...}
}
Kuten edellä mainittiin, "Tailwind Hyväksytty" -lähestymistapa on lisätä tunnit turvaluetteloon, mutta olen ASP.NET-tyyppi, joten HTML voitti.
Tein oikein, kun kieltäydyin luovuttamasta. Jokainen virheilmoitus oli oppimistilaisuus. Jokainen rikkinäinen rakennus opetti minulle jotain uutta näiden työkalujen toiminnasta. Minulla oli selkeä visio – nopeasti lastaavat, optimoidut voimavarat – ja jatkoin iterointia, kunnes pääsin perille.
Siirtyminen CDN-pohjaisista riippuvuuksista moderniin niputusputkeen on ollut tämän blogin kannalta mullistavaa, mutta se ei ollut helppoa. Suorituskyvyn parantuminen on merkittävää, kehittäjäkokemus on huomattavasti parempi, ja minulla on paljon suurempi kontrolli optimoinnissa, mutta tänne pääsy vaati kuukausien kokeilun ja virheen.
Avainruokia:
ASP.NET Core -kehittäjille, jotka ovat tottuneet yksinkertaiseen CDN:ään, tämä tuntuu aluksi ylivoimaiselta. Se on normaalia. Tunsin samoin. Aloita pieni, siirry riippuvuuteen kerrallaan, äläkä pelkää rikkoa asioita kehitystyössä. Opit enemmän rikkinäisten rakennelmien vioista kuin koskaan.
Tässä jakamani kokoonpano edustaa kuukausien iterointia. Matkasi tulee olemaan erilainen, ja se on hyvä. Käytä tätä lähtökohtana, ei gospelina. Mukauta se tarpeisiisi, kokeiluun, äläkä lannistu epäonnistumisista – ne ovat osa prosessia.
Onko tämä blogi ylikehittynyt? Olisinko voinut käyttää CDN-levyjä ja käyttää aikaani muihin asioihin? Toki, mutta en olisi oppinut puoliakaan niin paljon, eikä minulla olisi tätä artikkelia kerrottavana kanssasi. Joskus ylisuunnittelussa ei ole kyse päämäärästä, vaan siitä, mitä matkan varrella oppii ja pystyy opettamaan siitä muille.
Jos luotat yhä CDN-levyihin etupään riippuvuudessasi, kannustan sinua kokeilemaan niputtamista. Aloita yhdestä kirjastosta. Katso, miltä se tuntuu. Ekosysteemi on kypsynyt merkittävästi, ja vaikka oppimiskäyrä on todellinen, kannattaa maksaa.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.