اجعل تطوير HTML متعدد الصفحات أقل مع Pug

مستوحاة من قصة حقيقيه

لنقم برحلة ...

تخيل أنك على قائمة الاتصال بوكالة مستقلة في مدينة من اختيارك. لنفترض الآن أنك تلقيت رسالة لطيفة في بريدك الوارد. تفتح الرسالة وتبدو طبيعية جدًا.

لدينا حاجة فورية لمطور أن يبدأ اليوم.

الرسالة وتبدو طبيعية جدًا.

لدينا حاجة فورية لمطور أن يبدأ اليوم.

كونك شخصًا يستمتع بتناول الطعام للبقاء على قيد الحياة ، فأنت تكتب بعض المعلومات وتقدم بطلب.

في غضون خمس دقائق من الضغط على زر الإرسال هذا ، ستتلقى مكالمة. بعد 10 دقائق من ذلك ، يمكنك الوصول إلى الخادم.

لا داعي للقول ، أنت على موعد نهائي. الموعد النهائي هو نهاية اليوم.

تفتح ملفات HTML وتنظر فيها ... في حالة رعب.

الشفرة في كل مكان ، فوضوية وغير منظمة. ناهيك عن أنه عليك إجراء تعديلات على الرأس والتذييل ... في خمس صفحات مختلفة.

أول شيء تفعله هو تشغيله من خلال Prettify (الحمد لله على Prettify). أدى ذلك إلى تنظيف الأمر ، ولكن هناك بعض المشاكل الأخرى. هذا موقع HTML ثابت ، مما يعني أن كل تغيير تجريه على العناصر العالمية (رأس الصفحة ، وتذييلها ، وما إلى ذلك) ، سيتعين عليك نسخه في كل ملف. أوه يا.

ماذا ستفعل؟؟؟

ببساطة ، ستعمل على إنشاء ملف Webpack للتعامل مع الجزء السيئ من كتابة HTML ، وستفعل ذلك بسرعة.

إليك ما ستحتاج إلى معرفته:

  • جافا سكريبت! (بسبب Webpack)
  • لغة البرمجة! (لأن هذا هو ما صنع الإنترنت)
  • CSS! (لأن من يحب الأشياء القبيحة؟)
  • الصلصال! (لأن هذا هو الهدف من هذه المقالة!)
  • npm (لأنه الله)
  • المعرفة الأساسية بسطر الأوامر (لأن القيام بالأشياء عبر التنزيلات أمر غبي ...)
  • تعرف من هو جيم كاري (لأن صور متحركة)

إذا لم تكن معتادًا على الكلب ، فلا يزال بإمكانك إدارة طريقك من خلال ذلك. لكن إذا كان لديك وقت ، فاقرأه. أوصي بتعلم الصلصال مع الصلصال. أو مستنداتهم. أعتقد أن هؤلاء لا بأس بهم أيضًا.

هذه هي الإصدارات التي استخدمتها لهذا:

  • محمل html: 0.5.5 ،
  • html-webpack-plugin: 3.2.0 ،
  • pug-html-loader: 1.1.5 ،
  • حزمة الويب: 4.12.0
  • حزمة الويب- cli: 3.0.8
  • npm: 6.1.0
  • العقدة: 10.4.0

تحديث: لقد صنعت مقطع فيديو! تحقق من ذلك إذا كنت لا تريد القراءة ، ولكنك تفضل الاستماع إلى صوتي لمدة 30 دقيقة.

الخطوة الأولى: تنظيم هيكل مشروعك

هذه هي الطريقة التي أرغب في تنظيم مجلدي بها لهذه الأنواع من المشاريع.

src/ oldHTML/ dist/ images/ css/ webpack.config

أود وضع كل HTML الأصلي في مجلد منفصل لا يمكنني حذفه عن طريق الخطأ. إن Webpack ألطف قليلاً من القول ، Gulp ، الذي قمت بحذف مجلد كامل من قبل؟ هذا الهيكل جيد بما يكفي لنبدأ.

الخطوة 2. رفع سرعة المحرك npm

جانبا: لقد عدت مؤخرًا إلى npmمن yarnلعدة أسباب. كان أحدها أنه توقف عن العمل ولم يكن لدي سوى القليل من الصبر لجعله يعمل مرة أخرى. مقال مثير للاهتمام هنا ، إذا كنت تريد قراءة المزيد.

على أي حال ، init أن npm.

npm init -y

ملاحظة: (the -y هي إذا كنت لا تريد الإجابة على أي من أسئلتها)

تثبيت التبعيات التطويرية.

لا تقلق ، سأشرح كل واحد ونحن نذهب.

npm install -D webpack webpack-cli pug-html-loader html-webpack-plugin html-loader

أضف بعض البرامج النصية إلى package.json

بشكل افتراضي ، يحتوي package.json على نص برمجي واحد ، لكننا نحتاج إلى إضافة القليل.

"dev": "webpack --watch --mode development", "prod": "webpack --mode production"

هذان هما اللذان أود تضمينهما. الأول سيشغل Webpack في وضع التطوير (ملاحظة: علامة --mode جديدة في Webpack 4) وراقب تغييرات الملف. والثاني هو عندما نريد تشغيل Webpack في الإنتاج ، فهذا عادة ما يقلل من الأشياء.

يجب أن يبدو مثل هذا:

"name": "pugTut", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "dev": "webpack --watch --mode development", "prod": "webpack --mode production" }, .....more code

أنشئ ملفي بداية لاختبار تهيئة Webpack

يحتاج Webpack إلى نقطة دخول ، لذلك دعونا نصنع واحدة. قم بإنشاء app.js في المجلد / src . يمكن أن تكون فارغة. لا يهم. يحتاج أيضًا إلى ملف الصلصال الأولي ليتم تجميعه. أنشئ ملف index.pug في المجلد / src أيضًا.

قم بإنشاء وإعداد webpack.config.js في الدليل الجذر

Alright, if you haven’t used Webpack before, I’m going to walk through each part individually to give you (and hopefully me) an idea of wtf is going on in this config file.

First, let’s declare our dependencies.

// webpack.config.js const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin');

path is a native Node dependency, so you shouldn’t have to worry about that being required in your package.json.

Webpack is, well Webpack…

HtmlWebpackPlugin is how we extract HTML. I’m not an expert on how Webpack works. From what I understand, since it is designed to consume JavaScript, we have to have loaders in our config file to pull out things like HTML and CSS. HtmlWebpackPlugin is how we do something useful with the HTML that gets extracted from the loaders.

Cool? Next step…

const pug = { test: /\.pug$/, use: ['html-loader?attrs=false', 'pug-html-loader'] };

This method is used by Wes Bos and I really like it, so I use it. We have to define rules on how to handle certain file types, for example .pug or .css. Putting it into a variable makes it more legible, in my opinion. Anyways, we setup a test case with a regexp, then define the loaders we want to use. For whatever reason, the loaders are listed in reverse order of what you’d think. I’m sure there is an explanation but I couldn’t find it.

Confused? What that means is, if we want to use pug to compile to HTML, we write it in the order above: our html loader ->pug loader. However, in reality when the code runs, it runs the pug loader first…then the HTML loader. Yep.

Note: Don’t worry about ?attrs=false for right now, I’ll explain it a bit later.

Cool? Next step…

const config = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, module: { rules: [pug] }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/index.pug', inject: false }) ] }; module.exports = config;

Holy Crap. That’s a lot of stuff. Let’s break it down.

entry is simply the entry point for our JS file.

output defines where we want our JS file to go. This is not where our HTML files will go. As mentioned above, path is a node module. __dirname is a variable we can get from Node. The filename is what we want to call our JS file. The [name] is a substitution. In this case, it uses the file name of the entry file. You can also use [hash] if you want a unique identifier.

module defines the different modules. For the purpose of this tutorial, there is only one module with one set of rules. rules defines the rules we will use for that module. We throw the pug variable we made earlier into there. So nice, so clean.

Finally, plugins is where we get to add any third party stuff. In our case, we are using HtmlWebpackPlugin to do something with our pug files.

filename is what we want our HTML file to be called. template is the pug file that are compiling. inject is: “inject all assets into the given template.” I have it set to false because…well, honestly I don’t remember.

One of the crappiest things about HtmlWebpackPlugin is that you have to create an entry for EVERY HTML file. I tried to figure a way around it, but found no simple solutions.

// webpack.config.js const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const pug = { test: /\.pug$/, use: ['html-loader?attrs=false', 'pug-html-loader'] }; const config = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, module: { rules: [pug] }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/index.pug', inject: false }) ] }; module.exports = config;

Before we move on, let’s make sure our code works! Run the script.

npm run dev

If all went well, you should see something like this:

We’ve come a long way. Here’s a present:

Step 3. Break up the pages into partials

This is where magic starts happening. I know it seems like we’ve been working for a while with very little gain, but trust me…it was worth it.

One of the most important features for pug is the partials. The idea is to have one file that holds most of your global code (head, header, footer, nav, and so on) and have individual files for all your content.

Let’s make a couple files. You should have created the index.pug file already, but let’s make one more, layout.pug.

src/ - index.pug - layout.pug

Step 4. Setup layout file

The layout file is basically the main template for your whole site. It will have hold all the global stuff, for example head, header and footer.

//- layout.pug doctype html html head title I'm a title body block header block content block footer script(src="somescript.js")

I guess something to explain is that pug is all based on indentation, similar to YAML. It is glorious, because that means no more closing tags! However, this can throw some, especially those with crappy indentation to begin with. So just make sure to start slow and make sure everything is indented correctly and you’ll be fine.

Looking at our layout.pug file, you’ll see some familiar HTML tags mixed with unfamiliar ones. I highly suggest downloading syntax highlighting for pug in your editor of choice. If you’re using VSCode, it should come with it by default. Thanks Microsoft.

I think it’s pretty easy to figure out, but let’s take a look at the meat of the document to make sure we know what’s going on.

head title I'm a title body block header block content block footer script(src="somescript.js")

head, body, title and script are normal tags, but what the hell is block? block is how we define dynamic content. Basically, this is telling pug that some content is going to go in here. Hopefully it’ll make more sense when we create our individual page files.

Step 5. Create more partials

Let’s make use of that index.pug file.

//- index.pug extends layout block content p Woah.

Looking at our index file, it seems awfully small for a whole HTML page. That’s because of that little extends fella. extends tells pug that you want to use another pug file as the template, in our case layout. Then below that block content is in reference to what we put in our layout.pug file.

If you have your Webpack still running in the background, it should recompile and you’ll get a fresh new index.html in your dist/ folder. If not, run Webpack again.

Step 6. Grab all the old HTML

Those starter files are fine and dandy, but we need to make some real progress. We need to start grabbing that HTML and using it! Luckily, pug will recognize regular old HTML tags, so you can literally copy all the HTML content you want and just paste it in there.

It might look something like this:

extends layout block content 

blerb

Woah.

Alright, it’s not really that simple.

Like I mentioned, pug is based on indentation. To make life easier on yourself, I suggest removing all indentation from the HTML file before pasting into the pug file. It will mostly work, but you’ll probably have to finagle it a bit. Lucky for us, pug-html-loader will tell us what’s wrong with it when it tries to compile. There are some examples of common problems in the next Step.

Step 7. Start optimizing

لن أكذب ، عندما تستخدم HTML لأول مرة ، لن يعجبك Webpack. إليك بعض الأشياء التي يجب البحث عنها:

الصور

  1. تأكد من أن الروابط إلى الصور جيدة. لأي سبب من الأسباب ، غالبًا ما يفشل إذا كان src = "images /" بدلاً من src = "/ images /"

2. لقد وعدت سابقًا بالعودة إلى ما ?attrs=falseكان ، حسنًا ، ها نحن!

هذا هو دعاية مغالى فيها من موقع تحميل html يشرح ما يفعله ذلك.

لتعطيل معالجة سمة العلامة تمامًا (على سبيل المثال ، إذا كنت تتعامل مع تحميل الصور من جانب العميل) ، يمكنك تمرير attrs=false.
html-loader?attrs=false 

جافا سكريبت

لا يلعب الصلصال بشكل جيد مع JS في علامات البرنامج النصي. إذا كنت تلصق علامات برامج نصية لفتح وإغلاق JS بشكل منتظم ، فقد تعمل بشكل جيد. ومع ذلك ، إذا كنت ترغب في الاستفادة من علامة البرنامج النصي للصلصال ، فقط تأكد من إضافة نقطة في النهاية ، مثل هذا:

Step 8. Make more pages and start converting to pug tags

Clearly it’s useless if you are only doing the index page. For whatever you’re doing, just create a new file for each page you want. Also, make sure to make new HtmlWebpackPlugin entries in the plugins section in Webpack.

It’ll end up looking like this:

//webpack.config.js ...previous code... plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/index.pug', inject: false }), new HtmlWebpackPlugin({ filename: 'contact.html', template: 'src/contact.pug', inject: false }) ] ...more code...

You don’t have to convert everything to pug format immediately. In fact, if you have a huge site with a crap ton of HTML, then you can do it as you go, but it does make it easier.

Includes

لن يكون هذا تعليميًا جيدًا جدًا إذا لم نتحدث عن التضمينات. تذكر تلك الكتل في ملف التخطيط؟ حسنًا ، إذا كنت لا تريد أن يكون ملف التخطيط عملاقًا ، فيمكنك إنشاء ملفات منفصلة سيتم سحبها في وقت الترجمة. على سبيل المثال ، إذا كنت ترغب في إنشاء ملف واحد يحتوي على جميع معلومات الرأس. تقسيمها بهذه الطريقة يساعد أيضًا بشكل كبير مع المسافة البادئة.

قم بإنشاء "header" ملف جديد في مجلد جديد "include":

src/ -- includes/ header.pug

في هذا الملف ، ضع كل ما تريد أن يكون في رأس الصفحة.

//- header.pug header h1 I'm a header

عد الآن إلى layout.pug وقم بتضمينه.

//- layout.pug doctype html html head title I'm a title body block header include includes/header block content block footer script(src="somescript.js")

الخطوة 7. هل ترغب في الحصول على فخامة؟

هناك الكثير من الأشياء التي يمكنك القيام بها مع الصلصال وحزمة الويب. ومع ذلك ، أعتقد أننا وصلنا إلى نهاية الأساسيات. لا يزال ، تحقق من mixins. هذه الأشياء مدهشة.

تغليف

أقترح بشدة إدخال HTML ببطء ، وإلا فسوف ينتهي بك الأمر إلى تصحيح أخطاء 1،000 مرة واحدة.