Euromind
  • Javascript
    • Javascript

      Historiske administrative geografier i Google Maps

      20. april, 2022

      Javascript

      Kierkegaard injiceret med Javascript

      15. april, 2022

      Javascript

      Dansk evighedskalender

      7. december, 2020

      Javascript

      API til Statistikbanken

      21. september, 2019

      Javascript

      IntersectionObserver

      9. august, 2019

  • CSS/SCSS
    • CSS/SCSS

      Kierkegaard injiceret med Javascript

      15. april, 2022

      CSS/SCSS

      Dansk evighedskalender

      7. december, 2020

      CSS/SCSS

      Variable fonte med dansk tegnsæt i open source

      11. august, 2019

      CSS/SCSS

      Progressbar for dokumentposition

      31. juli, 2019

      CSS/SCSS

      Media Query i 2019

      18. juli, 2019

  • C#
    • C#

      Historiske administrative geografier i Google Maps

      20. april, 2022

      C#

      Authentication for IOS og Android med Firebase i…

      4. oktober, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 3

      5. september, 2019

      C#

      Hurtig eksport til Excel

      4. september, 2019

      C#

      Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

      2. september, 2019

  • Javascript
    • Javascript

      Historiske administrative geografier i Google Maps

      20. april, 2022

      Javascript

      Kierkegaard injiceret med Javascript

      15. april, 2022

      Javascript

      Dansk evighedskalender

      7. december, 2020

      Javascript

      API til Statistikbanken

      21. september, 2019

      Javascript

      IntersectionObserver

      9. august, 2019

  • CSS/SCSS
    • CSS/SCSS

      Kierkegaard injiceret med Javascript

      15. april, 2022

      CSS/SCSS

      Dansk evighedskalender

      7. december, 2020

      CSS/SCSS

      Variable fonte med dansk tegnsæt i open source

      11. august, 2019

      CSS/SCSS

      Progressbar for dokumentposition

      31. juli, 2019

      CSS/SCSS

      Media Query i 2019

      18. juli, 2019

  • C#
    • C#

      Historiske administrative geografier i Google Maps

      20. april, 2022

      C#

      Authentication for IOS og Android med Firebase i…

      4. oktober, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 3

      5. september, 2019

      C#

      Hurtig eksport til Excel

      4. september, 2019

      C#

      Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

      2. september, 2019

Euromind
CSS/SCSSHTMLJavascriptWebdesign

GULP møder AMP – del 2

af Per Lindsø Larsen 7. juni, 2019
skrevet af Per Lindsø Larsen 7. juni, 2019
GULP møder AMP – del 2

Fonte

I nærværende template kan der i _variables.scss vælges mellem Roboto, Lato og Agrandir som forvalgt font-type. Sidstnævnte er en variabel font. Variable fonte blev i 2016 annonceret af Adobe, Apple, Google og Microsoft. Alle størrelser og variationer er i en og samme fil og der er angivet reduktion i den samlede størrelse af font-fil(er) på 88%. Det er ikke helt skævt i forhold til nedenstående sammenligning mellem at bruge Roboto og den variable Agrandir i dette projekt. Samtidig bliver der sparet godt 200 ms i indlæsningstid – og det er jo i sidste ende hvad AMP handler om.

Variable fonte er efterhånden understøttet i alle væsentlige browsere: Chrome, Edge, Firefox, Safari, IOS Safari og Android browser. Det samme gælder for det kompakte font-format .woff2.

Om man så visuelt kan lide den variable font er en anden snak. De fleste tilgængelige variable fonte i open-source har – i modsætning til Agrandir – problemer med æøå.

Indsættelse af <script> for komponenter

For hver gang der anvendes et nyt AMP-komponent i HTML-koden skal der tilføjes et eller flere script-tags, der loader det anvendte komponent. Anvendes <amp-autocomplete> skal f.eks. tilføjes den tilhørende javascript-extension:

<script async custom-element="amp-autocomplete" src="https://cdn.ampproject.org/v0/amp-autocomplete-0.1.js"></script>

Der skal også holdes styr med versioneringen. Nogle scripts er i 0.1 andre i 0.2 osv. I alt er der i skrivende stund 138 forskellige javascript-extensioner, så uden hjælp fra GULP er det en mildest talt bøvlet del af AMP.

Gulp må nødvendigvis have de fornødne oplysninger om filnavne og versionsnumre for disse script. Det skyldes muligvis min egen indskrænkethed, men jeg har ikke været i stand til noget sted at finde en let tilgængelig oversigt eller endnu bedre en json-fil med oplysninger om AMP komponenternes javascript-filer. Nedenstående C#-kode vil derimod gøre arbejdet og hente de nødvendige informationer til en fil AmpExtensions.json, der så efterfølgende kan hentes ind i gulpfile.js. AMP projektets github undersøges for underbiblioteker, der indeholder navne på extensioner og hver komponents md-dokument søges for yderligere info. Det lyder bøvlet, men tager kun et halvt minut og virker efter hensigten:

       static void Main(string[] args)
        {
            string url = "https://github.com/ampproject/amphtml/tree/master/extensions";
            string path = "/ampproject/amphtml/tree/master/extensions/";
            string cdn = "https://cdn.ampproject.org/v0/";
            TextWriter tw = new StreamWriter("AmpExtensions.json");
            tw.WriteLine("[");
            using (WebClient client = new WebClient())
            {
                string s = client.DownloadString(url);
                Regex ItemRegex = new Regex(path + @"(amp-[\w|-]*)",
                    RegexOptions.Compiled);
                MatchCollection m = ItemRegex.Matches(s);
                Console.WriteLine("Fundet " + m.Count + " extensioner.");
                var itemcounter = 0;
                int counter = 1;
                foreach (Match ItemMatch in ItemRegex.Matches(s))
                {
                    Console.WriteLine(counter + "/" + m.Count + " " + ItemMatch.Groups[1].Value); 
                    string componentName = ItemMatch.Groups[1].Value;
                    using (WebClient client2 = new WebClient())
                    {
                        try
                        {
                 string extPage = client.DownloadString(String.Format("{0}/{1}/{1}.md", url, componentName));
                            Regex requiredRegex = new Regex(cdn + @"(amp-[\w|-]*\d.\d.js)",
                                RegexOptions.Compiled);
                            foreach (Match requiredMatch in requiredRegex.Matches(extPage))
                            {
                                string filename = requiredMatch.Groups[1].Value;
                                string match = "";
                                Regex exampleRegex = new Regex(
                                    @"<<span class=""pl-ent"">" + componentName + "</span>",
                                    RegexOptions.Compiled);
                                if (exampleRegex.Match(extPage).Value.Trim().Length > 0)
                                    match = "<" + componentName + " ";
                                else
                                    match = componentName;
                                if (componentName == "amp-bind") match = "<amp-state";
                                if (itemcounter > 0) tw.WriteLine("},");
                                tw.WriteLine("{");
                                tw.WriteLine("\"match\": \"" + match + "\",");
                                tw.WriteLine("\"name\": \"" + componentName + "\",");
                                tw.WriteLine("\"file\": \"" + filename + "\"");
                                itemcounter++;
                            }
                        }
                        catch (Exception e)
                        {
                        }
                    }
                    counter++;
                }
            }
            tw.WriteLine("}");
            tw.WriteLine("]");
            tw.Close();
        }

Indholdet i den dannede AmpExtensions.json har formatet:

[
{
"match": "<amp-3d-gltf ",
"name": "amp-3d-gltf",
"file": "amp-3d-gltf-0.1.js"
},
{
"match": "<amp-3q-player ",
"name": "amp-3q-player",
"file": "amp-3q-player-0.1.js"
},
{
"match": "amp-access-laterpay",
"name": "amp-access-laterpay",
"file": "amp-access-0.1.js"
},
{
"match": "amp-access-laterpay",
"name": "amp-access-laterpay",
"file": "amp-analytics-0.1.js"
},
{
"match": "amp-access-laterpay",
"name": "amp-access-laterpay",
"file": "amp-access-laterpay-0.2.js"
}

// og ca 135 tilsvarende .......
]

Nogle extensioner kræver mere end en js-fil indlæst, hvilket der også er taget højde for. I ovenstående udtræk ses f.eks. at amp-access-laterpay kræver både amp-analytics-0.1.js, amp-access-0.1.js og amp-access-laterpay-0.2.js. Ligeledes er på baggrund af anførte eksempler i de markdown-filer, som er gennemtrævlet, søgt dannet det RegEx-mønster, der skal søges på i html-dokumentet, for at afgøre om det respektive script-tag skal tilføjes i html-dokumentets head-sektion. Da versionsnumre skifter og nye komponenter kommer til, er det nok nødvendigt at opdatere en gang imellem.

AmpExtension.json kan hentes ind i gulpfile.js på samme måde som et hvilket som helst andet plugin. Fil-extensionen “.json” kan udelades:

const AmpExtensions = require('./AmpExtensions');

Filen kan nu anvendes i task’en processHTML

var _processHTML = (file)=> {
    const filename = path.basename(file.path);
    const cssFilename = path.basename(file.path, ".html") + ".min.css";
    let cssContent = fs.readFileSync(buildDir + "/" + cssFilename, "utf8");
    let filecontent = file.contents.toString();
    AmpExtensions.forEach(function (item) {
    var re = new RegExp(item.match);    
    if (filecontent.match(re) != null)  {

        let custom = (item.name=="amp-mustache") ? "custom-template" : "custom-element";   
        let tag = `<script async ${custom}="${item.name}" 
                   src="https://cdn.ampproject.org/v0/${item.file}"></script>`    
        if (!filecontent.includes(tag))
                   filecontent = filecontent.replace('<head>', `<head>\n${tag}`);
        }
    });
    filecontent = filecontent.replace(`<a href="${filename}">`, `<a href="${filename}" class="selected">`);
    return filecontent.replace('<style amp-custom>', '<style amp-custom>' + cssContent);
}


gulp.task('processHTML', () => {
    return gulp.src(buildDir + "/*.html")
        .pipe(tap((file) => {
            var filecontent = _processHTML(file);
            file.contents = Buffer.from(filecontent);
        })) 
        .pipe(strip())
        .pipe(htmlmin({ collapseWhitespace: true }))
        .pipe(gulp.dest(distDir));
});

gulp.task('processHTMLChanged', () => {
    return gulp.src(buildDir + "/*.html")
        .pipe(changed(distDir))
        .pipe(tap((file) => {
            var filecontent = _processHTML(file);
            file.contents = Buffer.from(filecontent);
        }))
        .pipe(strip())
        .pipe(htmlmin({ collapseWhitespace: true }))
        .pipe(gulp.dest(distDir));
});

For hver enkelt html-fil i build-folderen tappes ind i html-koden og søges for AMP-tags, som kræver en eller flere javascript filer. I givet fald tilføjes de til <head>. Samtidig kopieres indhold fra den tilhørende css-fil i build-folderen til <style amp-custom>. Alle kommentarer strippes ud af filen og den komprimeres med htmlmin. Linjen filecontent = filecontent.replace(<a href="${filename}">, <a href="${filename}" class="selected">); er ikke nødvendig, men tilføjer blot css-klassen “selected” til ethvert link, der refererer til siden selv. Det giver mulighed for at give særlig farve til f.eks. dette menupunkt i side-bar. Herefter gemmes den færdige html-fil i dist-folderen. Der tilføjes en task processHTMLChanged, der gør det samme, men kun for html-filer, der er blevet ændret.

Komprimering af billeder.

Task’en imagemin tager alle billed-filer i i /src/html/images, komprimerer dem og kopierer dem til /dist/images. Gulp sættes til at overvåge ændringer i /src/html/images og vil med imageminChanged komprimere og kopiere nye filer.

 gulp.task('imagemin', () =>
 gulp.src(scrHtmlDir + '/images/*')
     .pipe(imagemin())
     .pipe(gulp.dest(distDir + '/images'))
);

gulp.task('imageminChanged', () =>
gulp.src(scrHtmlDir + '/images/*')
    .pipe(changed(distDir + '/images'))
    .pipe(imagemin())
    .pipe(gulp.dest(distDir + '/images'))
);


gulp.watch([scrHtmlDir + "/images/*"], gulp.series('imageminChanged'));

Et par andre nyttige tasks

Når der i Visual Studio Code oprettes et nyt HTML-dokument i /src/html vil det være rart, hvis den automatisk får indsat template-kode, så f.eks. sidebar, header og footer og det nødvendige indhold til <head> med det samme er til stede, så vi kan koncentrere os om det reelle indhold. Det sørger task’en newFile for. Den ser efter, om der oprettes en ny fil uden indhold. Hvis det er tilfældet, så indsættes indholdet af /src/tempates/template.html . Denne template integrerer i dette projekt andre templates for sidebar, header footer m.v.

<!doctype html>
<html amp lang="da">
<head>
        <partial src="_head.html" title="GULP møder AMP"></partial>
</head> 
<body id="main">
        <partial src="_sidebar.html" title="GULP møder AMP" subtitle="Code-To-Go"></partial>
  <div class="theme">
    <partial src="_header.html" title="Gulp møder AMP"></partial>
<!-- INDSÆT INDHOLD-->    

<!-- Indsæt indhold slut-->
    <partial src="_footer.html" title=""></partial>
  </div> 
</body>
</html>

Task’en updateLauchJson opdaterer ../.vscode/launch.json til at pege den html-fil i /dist der er slutresultatet af den aktuelle fil, der redigeres i VS Code. De opdateres bl.a. med den port, som er valgt i gulpfile.js. Under Debug i VS Code eksisterer nu valgmuligheden “Åbn localhost i Chrome“. Herefter vil ændringer i html , data-json, templates, scss bliver live-opdateret i browseren.

gulp.task('updateLaunchJson',  () => {
   return gulp.src('./.vscode/launch.json')
    .pipe(jeditor((json) => {
    json.configurations[0].url = uri + "/${fileBasename}";
        return json; 
      }))
      .pipe(gulp.dest('./.vscode'));
 });

Når GULP startes op slettes alt indholdet i /build og /dist folderne. Det er en god fremgangsmåde for at sikre, at der ikke aflejrer sig unødvendige filer og billeder fra tidligere tider, men kun er det absolut nødvendige. Det sørger task’en clean for.

gulp.task('clean', () => {
    return gulp.src([buildDir, distDir + "/*.html",distDir + "/data/*.", distDir +  "/images/*" ], { read: false, allowEmpty: true })
        .pipe(clean())
});

Task’en copy sørger for at andre filer i /src – dette projekt robots.txt and favicon.ico – er opdaterede i /dist når gulp starter op:

 gulp.task('copy', () =>{
    return gulp.src([scrHtmlDir + "/robots.txt",scrHtmlDir + "/favicon.ico", scrHtmlDir + "/data/*.json"])
    .pipe(copy(distDir,{ prefix: 2 }))
    .pipe(gulp.dest(distDir));
 });

GULP’s endelige arbejdsgang

Når Gulp startes op i rod-biblioteket med filen gulpfile.js køres task’en default, der fjerner indhold fra /build og /dist, kopierer data-json filer til /dist. launc.json i ./.vscode opdateres med den host og port, som devserveren kører på. Billeder i /src/html/images komprimeres og kopieres til /dist/images. Scss kompileres og kopieres til style.css i /build. Templates injiceres i html-filer og kopieres til /build. Fore hver html-fil i /build findes den nødvendige css og kopieres til /build /[filnavn].css og minificeret [filnavn]-.min.css. For hver enkelt html-fil i /build injiceres de nødvendige script-tags for anvendte AMP-komponenter og minificeret css injiceres i <style amp-custom>. Den færdige AMPHTML-fil kopieres til /dist og AMP-valideres:

Devserveren startes op og viser sitet. Browser opdateres ved enhver ændring i /dist.

Mens dev-serveren ovevåger ændringer i /dist-folderen, så overvåger GULP ændringer i /src. Ændringer aktiverer batch-task’en process, der gør følgende:
Kompilerer scss til css, injicerer templates i html. filtrerer nødvendig css til hver html-fil, injicerer script-tags og amp-custom og AMP-validerer siderne. Når de kopieres til /dist aktiveres devserveren og browseren opdateres. processChanged, gør det samme, men kun for den html-fil, der er ændret.

gulp.task('process', gulp.series('sass', 'injectPartials', 'createAMPCustom', 'processHTML', 'validate'));
gulp.task('processChanged', gulp.series('newfile', 'injectPartialsChanged','createAMPCustom', 'processHTMLChanged', 'validate'));

gulp.task('default', gulp.series('clean', 'updateLaunchJson', 'copy', 'imagemin' , 'process', 'serve'));

gulp.watch(scssDir +  "/*.scss", gulp.series('process'));

gulp.watch([scrHtmlDir + "/*.html"],   gulp.series('processChanged'));
gulp.watch([templateDir + "/*.html"], gulp.series( 'process'));
gulp.watch([scrHtmlDir + "/data/*.json"], gulp.series('copy', 'process'));
gulp.watch([scrHtmlDir + "/images/*"], gulp.series('imageminChanged'));

Projektets index.html henter fra de respektive templates header, footer og sidebar og integrerer en amp-carousel og amp-list, der begge henter data fra json. Den færdige AMP-version af siden i /dist-folderen fylder ikke mere end 12.5 kb inkl. style. Med GULP har vi fået det hele optimeret og skabt et godt udgangspunkt for at påbegynde den egentlige udvikling af indholdet.

AMPGulp
0 Kommentarer
1
FacebookTwitterPinterestEmail
forrige post
Stylometri i C# – del 2
næste post
WEBP billedformatet

Relaterede indlæg

Historiske administrative geografier i Google Maps

20. april, 2022

Kierkegaard injiceret med Javascript

15. april, 2022

Dansk evighedskalender

7. december, 2020

Headless browser på 10 minutter

25. juli, 2020

API til Statistikbanken

21. september, 2019

Variable fonte med dansk tegnsæt i open source

11. august, 2019

IntersectionObserver

9. august, 2019

Progressbar for dokumentposition

31. juli, 2019

Navngivne RegEx-grupper i ECMAScript 2018

29. juli, 2019

RegEx: Unicode og Look Backward i ECMAScript 2018

24. juli, 2019

Efterlad en kommentar Afbryd svar

Gem mit navn, email, og website i denne browser til senere kommentarer.

Seneste indlæg

  • Historiske administrative geografier i Google Maps

    20. april, 2022
  • Kierkegaard injiceret med Javascript

    15. april, 2022
  • Dansk evighedskalender

    7. december, 2020

Kategorier

  • C#
  • CSS/SCSS
  • Excel
  • HTML
  • Javascript
  • Mobile
  • Webdesign
  • Xamarin

Om mig

Om mig

Per Lindsø Larsen

Freelance fullstack developer bosat i Aarhus.

Du kan hyre mig til korterevarende projekter eller konkrete opgaveløsninger.

Pæn rabat til non-profit organisationer og foreninger.

Når jeg ikke koder, deltager jeg løbende i diverse spændende forskningsprojekter om alt andet end kodning.

Keep in touch

Facebook Twitter Email Github

Tags

Adresser AMP AMP Story Android API Billedformater Billedoptimering Brand C# Codepen Cordova CPR Crome DevTools CSS Debug Ecmascript Excel Fonte Gmail Gulp HTML Ikoner IOS Javascript JsFiddle Machine Learning Mail Mediaquery ML.NET Mobile RegEx SCSS SMTP Stylometri Visual Studio Webdesign Xamarin

Nyhedsbrev

Timeld nyhedsbrev for info om nye blog-indlæg, tips m.v.

  • Facebook
  • Twitter
  • Email
  • Github

@2019 - Euromind.com - Code-To-Go. All Right Reserved.
lindsoe@gmail.com - mobil: 42797273


Tilbage til top
Euromind
  • Javascript
    • Javascript

      Historiske administrative geografier i Google Maps

      20. april, 2022

      Javascript

      Kierkegaard injiceret med Javascript

      15. april, 2022

      Javascript

      Dansk evighedskalender

      7. december, 2020

      Javascript

      API til Statistikbanken

      21. september, 2019

      Javascript

      IntersectionObserver

      9. august, 2019

  • CSS/SCSS
    • CSS/SCSS

      Kierkegaard injiceret med Javascript

      15. april, 2022

      CSS/SCSS

      Dansk evighedskalender

      7. december, 2020

      CSS/SCSS

      Variable fonte med dansk tegnsæt i open source

      11. august, 2019

      CSS/SCSS

      Progressbar for dokumentposition

      31. juli, 2019

      CSS/SCSS

      Media Query i 2019

      18. juli, 2019

  • C#
    • C#

      Historiske administrative geografier i Google Maps

      20. april, 2022

      C#

      Authentication for IOS og Android med Firebase i…

      4. oktober, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 3

      5. september, 2019

      C#

      Hurtig eksport til Excel

      4. september, 2019

      C#

      Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

      2. september, 2019

Populære indlæg

  • 1

    Stylometri i C# – del 2

    7. juni, 2019
  • 2

    Andersen, Grundvig, Kierkegaard og ML.NET – del 1

    11. august, 2019
  • 3

    Send email fra Javascript med Gmail API

    21. juni, 2019
  • 4

    Gmail, Yahoo og Outlook som SMTP-server

    18. april, 2019
  • 5

    API til Statistikbanken

    21. september, 2019
@2019 - Euromind.com - Code-To-Go. All Right Reserved.
lindsoe@gmail.com - mobil: 42797273

Læs ogsåx

Media Query i 2019

18. juli, 2019

MutationObserver

9. juli, 2019

Console.log() på stereoider

7. april, 2019