Last active
September 7, 2022 15:13
-
-
Save mistergraphx/e128cfaa1d9b6efb45bbb91da34606de to your computer and use it in GitHub Desktop.
gulp_webpack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* jshint node: true */ | |
'use strict'; | |
/** | |
* Usage général : | |
* | |
* - tâche "gulp" : fichiers compilés dans "/dist" (ni minifiés ni concaténés). | |
* Le client peut modifier, améliorer et mettre en prod lui-même. | |
* | |
* - tâche "gulp --prod" : fichiers compilés dans "/dist" (minifiés, concaténés, | |
* optimisés, etc.). Le client utilise tel quel. | |
*/ | |
/** | |
* Chargement et initialisation des composants utilisés | |
*/ | |
require('events').EventEmitter.defaultMaxListeners = 15; | |
var gulp = require('gulp'), | |
$ = require('gulp-load-plugins')(), | |
argv = require('yargs').argv, | |
stripDebug = require('gulp-strip-debug'), | |
terser = require('gulp-terser'), | |
gulpif = require('gulp-if'), | |
compiler = require('webpack'), | |
webpack = require('webpack-stream'), | |
through = require('through2'), | |
sass = require('gulp-sass')(require('sass')), | |
critical = require("./critical"), | |
replace = require('gulp-replace'); | |
var env = argv.env; | |
var debugEnabled = true; | |
var urlPrefix = 'local-'; | |
if (env === 'local') { | |
var jshint = require('gulp-jshint'); | |
var urlPrefix = 'local-'; | |
} else if (env === 'preprod') { | |
urlPrefix = 'preprod-'; | |
} else if (env === 'stage') { | |
urlPrefix = 'stage-'; | |
} else if (env === 'prod') { | |
debugEnabled = false; | |
urlPrefix = ''; | |
} | |
/** | |
* Configuration générale du projet et des composants utilisés | |
*/ | |
var project = { | |
name: 'nouvelobs', // nom du projet, utilisé notamment pour le fichier ZIP | |
url: 'https://' + urlPrefix + 'www.nouvelobs.com/', // url du projet, utilisée par browserSync en mode proxy | |
urlArticle: 'https://' + urlPrefix + 'www.nouvelobs.com/monde/20190916.OBS18496/quand-boris-johnson-compare-le-royaume-uni-a-hulk.html', // url d'une page article type pour le critical | |
ua: '?ua=gulp', | |
commonJSFile: 'common.bundle.js', // nom du fichier JS après concaténation | |
expopJSFile: 'expop.js', | |
xitiJSFile: 'xiticlicks.js', | |
configuration: { | |
// configuration des différents composants de ce projet | |
cssbeautify: { | |
indent: ' ' | |
}, | |
htmlExtend: { | |
annotations: false, | |
verbose: false | |
}, | |
imagemin: { | |
svgoPlugins: [{ | |
removeViewBox: false | |
}, | |
{ | |
cleanupIDs: false | |
} | |
] | |
} | |
} | |
}; | |
/** | |
* Chemins vers les ressources ciblées | |
*/ | |
var paths = { | |
root: './', // dossier actuel | |
src: './web/src/', // dossier de travail | |
dist: './web/dist/', // dossier destiné à la livraison | |
inlineCss: './app/front/views/partials/assets/css/', | |
distSubscription: './web/subscription/', // dossier destiné à la livraison | |
vendors: './node_modules/', // dossier des dépendances du projet | |
assets: 'assets/', | |
styles: { | |
root: 'assets/css/', // fichier contenant les fichiers CSS & Sass | |
rootV7: 'assets/css/v7/', // fichier contenant les fichiers CSS & Sass pour la version 7 de knack | |
rootPlugins: 'assets/css/plugins/', // fichier contenant les feuilles de style pour les plugins | |
css: { | |
mainFile: 'assets/css/styles.css', // fichier CSS principal | |
mainFileV2: 'assets/css/stylesV2.css', | |
mainHeadlessFile: 'assets/css/headless.css', // fichier CSS principal but headless | |
mainHeadlessFileV2: 'assets/css/headlessV2.css', | |
articleFileV2: 'assets/css/articleV2.scss', // fichier Sass spécifique à la page d'article | |
articleHeadlessFileV2: 'assets/css/articleV2-headless.scss', | |
files: 'assets/css/*.css' // cible tous les fichiers CSS | |
}, | |
sass: { | |
homeFile: 'assets/css/v7/home.scss', // fichier Sass homepage | |
homeHeadlessFile: 'assets/css/v7/home-headless.scss', // fichier Sass homepage but headless | |
mainFile: 'assets/css/styles.scss', // fichier Sass principal | |
mainFileV2: 'assets/css/stylesV2.scss', | |
mainHeadlessFile: 'assets/css/headless.scss', // fichier Sass principal but headless | |
mainHeadlessFileV2: 'assets/css/headlessV2.scss', | |
articleFileV2: 'assets/css/articleV2.scss', // fichier Sass spécifique à la page d'article | |
articleFileV2Full: 'assets/css/articleV2-full.scss', // Article large en theme V2 | |
articleFileV2FullHeadless: 'assets/css/articleV2-full-headless.scss', // Article large en theme V2 but headless | |
articleFileV2Dossier: 'assets/css/articleV2-dossier.scss', // Theme V2 Dossier | |
articleHeadlessFileV2: 'assets/css/articleV2-headless.scss', | |
mainFileAMP: 'assets/css/styles-amp.scss', // fichier Sass AMP | |
oFile: 'assets/css/o.scss', // fichier Sass spécifique à Ô | |
//oHeadlessFile: 'assets/css/o-headless.scss', // fichier Sass spécifique à Ô | |
headerAndFooterFile: 'assets/css/headerAndFooter.scss', | |
headerAndFooterFileV2: 'assets/css/headerAndFooterV2.scss', | |
subscriptionFile: 'assets/css/subscription.scss', | |
subscriptionHeadlessFile: 'assets/css/subscription-headless.scss', | |
subscriptionAreaFile: 'assets/css/subscriptionArea.scss', | |
subscriptionAreaHeadlessFile: 'assets/css/subscriptionAreaHeadless.scss', | |
subscriptionStepsFile: 'assets/css/subscriptionSteps.scss', | |
subscriptionStepsHeadlessFile: 'assets/css/subscriptionStepsHeadless.scss', | |
widget2022File: 'assets/css/widget2022.scss', | |
miscFile: 'assets/css/misc.scss', // fichier Sass spécifique aux petites pages du site | |
miscHeadlessFile: 'assets/css/misc-headless.scss', // fichier Sass spécifique aux petites pages du site but headless | |
promosFile: 'assets/css/promos.scss', // fichier Sass spécifique aux pages promotionnelles | |
files: 'assets/css/**/*.scss' // fichiers Sass à surveiller | |
} | |
}, | |
scripts: { | |
root: 'assets/js/', // dossier contenant les fichiers JavaScript | |
common: 'assets/js/common/', | |
cmp: 'assets/js/es6/', | |
analytics: 'assets/js/analytics/', | |
expop: 'assets/js/expop.js' | |
}, | |
fonts: 'assets/fonts/', // fichiers typographiques à copier, | |
images: { | |
root: 'assets/img/', | |
files: 'assets/{,css/}img/**/*.{png,jpg,jpeg,gif,svg,webp}' | |
}, // fichiers images à compresser | |
cp: "assets/js/cp/", // fichiers à copier (doit être dans js pour l'URL en /bucket) | |
maps: '/maps' // fichiers provenant de sourcemaps | |
}; | |
/** | |
* Ressources JavaScript utilisées par ce projet (vendors + scripts JS spécifiques) | |
*/ | |
var jsCommonFiles = [ | |
paths.src + paths.scripts.root + 'smarttag.js', | |
paths.src + paths.scripts.root + 'load-attag.js', | |
paths.src + paths.scripts.common + 'attag-dynamic.js', | |
paths.src + paths.scripts.common + 'cookies.js', | |
paths.src + paths.scripts.common + 'modal.js', | |
paths.src + paths.scripts.common + 'try-forecast.js', | |
paths.src + paths.scripts.common + 'refresh.js', | |
paths.src + paths.scripts.common + 'scroll-helpers.js', | |
paths.src + paths.scripts.common + 'gsignin.js', | |
paths.src + paths.scripts.common + 'swg-activation.js', | |
]; | |
/** | |
* Tâche de gestion des erreurs à la volée | |
*/ | |
var onError = { | |
errorHandler: function (err) { | |
console.log(err); | |
this.emit('end'); | |
} | |
}; | |
var addGoogleFontWeight = function () { | |
return through.obj(function (chunk, enc, cb) { | |
const regex = /font-family:([^;}]+)/gmi; | |
let contents = `${chunk.contents}`; | |
let newContents; | |
let m; | |
while ((m = regex.exec(contents)) !== null) { | |
// This is necessary to avoid infinite loops with zero-width matches | |
if (m.index === regex.lastIndex) { | |
regex.lastIndex++; | |
} | |
const families = m[1].trim().split(',').map(e => e.trim().split(/["']/).join('')); | |
if (families.some((e) => | |
( | |
e.indexOf('SourceSerifPro') > -1 || | |
e.indexOf('Source Serif Pro') > -1 || | |
e.indexOf('Karla') > -1 || | |
e.indexOf('Newsreader') > -1 || | |
e.indexOf('Oswald') > -1 || | |
e.indexOf('Antonio') > -1 | |
) && | |
e.indexOf('-') > -1 && | |
e.indexOf('NewsreaderDisplay') === -1 && | |
e.indexOf('NewsreaderText') === -1 | |
)) { | |
newContents = contents.slice(0, m.index); | |
const [customFont, ...fallbacks] = families; | |
let [fontName, modifier] = customFont.split('-'); | |
if (fontName === 'SourceSerifPro') fontName = 'Source Serif Pro'; | |
let newFontFamily = `font-family:${JSON.stringify(fontName)}${fallbacks.length > 0 ? `, ${fallbacks.join(', ')}` : ''}`; | |
const isImportant = modifier.indexOf('!important') > -1; | |
modifier = modifier.split('!important').join('').trim(); | |
if (isImportant) { | |
newFontFamily += ' !important'; | |
} | |
switch (modifier) { | |
case 'extralight': | |
newFontFamily += '; font-weight:200'; | |
break; | |
case 'light': | |
newFontFamily += '; font-weight:300'; | |
break; | |
case 'regular': | |
newFontFamily += '; font-weight:400'; | |
break; | |
case 'medium': | |
newFontFamily += '; font-weight:500'; | |
break; | |
case 'semibold': | |
newFontFamily += '; font-weight:600'; | |
break; | |
case 'bold': | |
newFontFamily += '; font-weight:700'; | |
break; | |
case 'extrabold': | |
newFontFamily += '; font-weight:800'; | |
break; | |
default: | |
console.warn('unhandled modifier', modifier, customFont, newFontFamily) | |
} | |
newContents += newFontFamily; | |
newContents += contents.slice(m.index + m[0].length); | |
contents = newContents; | |
} | |
} | |
chunk.contents = Buffer.from(contents); | |
cb(null, chunk) | |
}); | |
} | |
exports.criticals = gulp.series(...critical.default(project, paths)); | |
/* ------------------------------------------------ | |
* Tâches de Check : js | |
* ------------------------------------------------ | |
*/ | |
function jsHint() { | |
return gulp | |
.src([...jsCommonFiles, | |
paths.src + paths.scripts.root + 'form/*.js', | |
paths.src + paths.scripts.root + '*.js']) | |
.pipe(jshint()) | |
.pipe(jshint.reporter('jshint-stylish')); | |
// .pipe(jshint.reporter()); // basic reporter | |
}; | |
/* ------------------------------------------------ | |
* Tâches de Build : css, js, img, fonts | |
* ------------------------------------------------ | |
*/ | |
// Tâche CSS : Sass + Autoprefixer + CSScomb + beautify + minify (si prod) | |
function css() { | |
return gulp | |
.src([ | |
paths.src + paths.styles.sass.homeFile, | |
paths.src + paths.styles.sass.homeHeadlessFile, | |
paths.src + paths.styles.sass.mainFile, | |
paths.src + paths.styles.sass.mainFileV2, | |
paths.src + paths.styles.sass.mainHeadlessFile, | |
paths.src + paths.styles.sass.mainHeadlessFileV2, | |
paths.src + paths.styles.sass.articleFileV2, | |
paths.src + paths.styles.sass.articleFileV2Full, | |
paths.src + paths.styles.sass.articleFileV2FullHeadless, | |
paths.src + paths.styles.sass.articleFileV2Dossier, | |
paths.src + paths.styles.sass.articleHeadlessFileV2, | |
paths.src + paths.styles.sass.oFile, | |
//paths.src + paths.styles.sass.oHeadlessFile, | |
paths.src + paths.styles.sass.headerAndFooterFile, | |
paths.src + paths.styles.sass.headerAndFooterFileV2, | |
paths.src + paths.styles.sass.subscriptionFile, | |
paths.src + paths.styles.sass.subscriptionHeadlessFile, | |
paths.src + paths.styles.sass.subscriptionAreaFile, | |
paths.src + paths.styles.sass.subscriptionAreaHeadlessFile, | |
paths.src + paths.styles.sass.subscriptionStepsFile, | |
paths.src + paths.styles.sass.subscriptionStepsHeadlessFile, | |
paths.src + paths.styles.sass.widget2022File, | |
paths.src + paths.styles.sass.miscFile, | |
paths.src + paths.styles.sass.miscHeadlessFile, | |
paths.src + paths.styles.sass.promosFile, | |
]) | |
.pipe($.plumber(onError)) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.init())) | |
.pipe(sass.sync().on('error', sass.logError)) | |
.pipe($.autoprefixer()) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)) | |
.pipe(addGoogleFontWeight()) | |
.pipe($.csso()) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.write(paths.maps))) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)); | |
}; | |
// Tâche CSS pour la nouvelle version de knack : Sass + Autoprefixer + CSScomb + beautify + minify (si prod) | |
function cssV7() { | |
return gulp | |
.src(paths.src + paths.styles.rootV7 + '*.scss') | |
.pipe($.plumber(onError)) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.init())) | |
.pipe(sass.sync().on('error', sass.logError)) | |
.pipe($.autoprefixer()) | |
.pipe(gulp.dest(paths.dist + paths.styles.rootV7)) | |
.pipe(addGoogleFontWeight()) | |
.pipe($.csso()) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.write(paths.maps))) | |
.pipe(gulp.dest(paths.dist + paths.styles.rootV7)); | |
}; | |
function cssPlugins() { | |
return gulp | |
.src(paths.src + paths.styles.rootPlugins + '*.scss') | |
.pipe($.plumber(onError)) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.init())) | |
.pipe(sass.sync().on('error', sass.logError)) | |
.pipe($.autoprefixer()) | |
.pipe(gulp.dest(paths.dist + paths.styles.rootPlugins)) | |
.pipe(addGoogleFontWeight()) | |
.pipe($.csso()) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.write(paths.maps))) | |
.pipe(gulp.dest(paths.dist + paths.styles.rootPlugins)); | |
}; | |
// Tâche CSS pour les fichiers AMP | |
function css_AMP() { | |
return gulp | |
.src(paths.src + paths.styles.sass.mainFileAMP) | |
.pipe($.plumber(onError)) | |
.pipe(sass.sync().on('error', sass.logError)) | |
.pipe($.autoprefixer()) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)) | |
.pipe($.csso()) | |
.pipe($.rename('styles-amp.css.volt')) | |
.pipe(replace('@charset "UTF-8";', '')) | |
.pipe(gulp.dest(paths.inlineCss)); | |
}; | |
// Tâche UNCSS pour le header et le footer | |
function uncss_header_footer() { | |
return gulp | |
.src(paths.dist + paths.styles.css.mainFile) | |
.pipe( | |
$.uncss({ | |
html: [project.url + 'header', project.url + 'footer'], | |
ignore: [ | |
/(js\-is\-sticky)/i, | |
/.fonts-loaded/, | |
/.modal/, | |
/.obs-abo/, | |
/.pop-co/, | |
/.opened/, | |
/.js-abonnes-nonmq/, | |
/.js-abonnes-nologged/, | |
/.js-abonnes-deconnect/, | |
/.slice/, | |
/.js-user-allowed/, | |
/@font-face/, | |
/.alert/, | |
/.is-paused/ | |
] | |
}) | |
) | |
.pipe($.rename('headerAndFooter.css')) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)); | |
}; | |
// Tâche UNCSS pour le header et le footer | |
function uncss_header_footer_V2() { | |
return gulp | |
.src(paths.dist + paths.styles.css.mainFileV2) | |
.pipe( | |
$.uncss({ | |
html: [project.url + 'headerV2', project.url + 'footerV2'], | |
ignore: [ | |
/(js\-is\-sticky)/mig, | |
/\.fonts-loaded/mg, | |
/\.modal/mg, | |
/\.obs-abo/mg, | |
/\.pop-co/mg, | |
/\.opened/mg, | |
/\.slice/mg, | |
/\.js-abonnes-nonmq/mg, | |
/\.js-abonnes-nologged/mg, | |
/\.js-abonnes-deconnect/mg, | |
/\.js-user-allowed/mg, | |
/@font-face/mg, | |
/\.alert/mg, | |
/\.is-paused/mg | |
] | |
}) | |
) | |
.pipe($.rename('headerAndFooterV2.css')) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)); | |
}; | |
// Tâche UNCSS pour le menu (pour N-E - Nouvelles Écritures) | |
function uncss_menu() { | |
return gulp | |
.src(paths.dist + paths.styles.css.mainFile) | |
.pipe( | |
$.uncss({ | |
html: [project.url + 'services' + project.ua], | |
ignore: [ | |
/\.opened/g, | |
/\.modal/g, | |
/\.js-is-sticky/g, | |
/\.js-user/g, | |
/\.js-abonnes/g, | |
'.icon-login.is-connect', | |
/\.ObsHeader-with/g, | |
'.ObsHeader-logo-brands', | |
/\.btn--base/g, | |
] | |
}) | |
) | |
.pipe($.rename('menu.css')) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)); | |
}; | |
// Idem que précédemment mais pour la V2 | |
function uncss_menu_V2() { | |
return gulp | |
.src(paths.dist + paths.styles.css.mainFileV2) | |
.pipe( | |
$.uncss({ | |
html: [project.url + 'services' + project.ua], | |
ignore: [ | |
/\.opened/, | |
/\.modal/, | |
/\.js-is-sticky/, | |
/\.js-user/, | |
/\.js-abonnes/, | |
'.icon-login.is-connect', | |
/\.ObsHeader-with/, | |
'.ObsHeader-logo-brands', | |
/\.btn--base/, | |
] | |
}) | |
) | |
.pipe($.rename('menuV2.css')) | |
.pipe(gulp.dest(paths.dist + paths.styles.root)); | |
}; | |
function jsStandalone() { | |
return gulp | |
.src([ | |
paths.vendors + 'jquery/dist/jquery.js', | |
paths.src + paths.scripts.root + 'form/*.js', | |
paths.src + paths.scripts.root + '*.js' | |
]) | |
.pipe(gulpif(debugEnabled === false, stripDebug())) | |
.pipe(terser({compress: {drop_console:env === 'prd'}})) | |
.pipe(gulp.dest(paths.dist + paths.scripts.root)); | |
}; | |
function jsWebpack() { | |
return gulp | |
.src(paths.src + paths.scripts.root) | |
.pipe($.plumber(onError)) | |
.pipe(webpack(require('./webpack.config.js'))) | |
// .pipe($.uglify()) | |
.pipe(gulp.dest(paths.dist + paths.scripts.root)); | |
}; | |
function jsCommon() { | |
var stream = gulp | |
.src(jsCommonFiles) | |
.pipe($.plumber(onError)) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.init())) | |
.pipe($.concat(project.commonJSFile)) | |
.pipe(gulpif(debugEnabled === false, stripDebug())) | |
.pipe(terser({compress: {drop_console:env === 'prd'}})) | |
.pipe(gulpif(env !== 'prod', $.sourcemaps.write(paths.maps))) | |
.pipe(gulp.dest(paths.dist + paths.scripts.root)); | |
return stream; | |
}; | |
// Tâche IMG : optimisation des images | |
function img() { | |
return gulp | |
.src(paths.src + paths.images.files) | |
.pipe($.changed(paths.dist + paths.assets)) | |
.pipe($.imagemin(project.configuration.imagemin)) | |
.pipe(gulp.dest(paths.dist + paths.assets)); | |
}; | |
exports.img = img; | |
// Tâche IMG : optimisation des images pre-commit hook | |
const path = require('path'); | |
gulp.task('optimg', function () { | |
var imgFile = argv.file ; | |
let destPath = path.dirname(imgFile); | |
return gulp | |
.src(imgFile) | |
.pipe($.imagemin(project.configuration.imagemin)) | |
.pipe(gulp.dest(destPath)); | |
}); | |
// Tâche FONTS : copie des fichiers typographiques | |
function fonts() { | |
return gulp | |
.src(paths.src + paths.fonts + '*') | |
.pipe($.changed(paths.dist + paths.fonts)) | |
.pipe(gulp.dest(paths.dist + paths.fonts)); | |
}; | |
// Tâche copy : copie des fichiers à conserver tel quel | |
function copy() { | |
return gulp | |
.src(paths.src + paths.cp + '**/*.*') | |
.pipe(gulp.dest(paths.dist + paths.cp)); | |
}; | |
/* ---------------------------------- | |
* Tâches principales : récapitulatif | |
* ---------------------------------- | |
*/ | |
// Tâche UNCSS : | |
exports.uncss = gulp.series(uncss_menu, uncss_menu_V2, exports.criticals); | |
exports.js = gulp.series(jsWebpack, jsCommon, jsStandalone); | |
var build = gulp.series( | |
css, | |
cssV7, | |
cssPlugins, | |
css_AMP, | |
exports.js, | |
img, | |
fonts, | |
copy, | |
exports.uncss, | |
); | |
exports.build = build; | |
var watchSass = () => gulp.watch( | |
paths.src + paths.styles.sass.files, | |
gulp.series(css, cssV7) | |
); | |
var watchJSCommon = () => gulp.watch( | |
jsCommonFiles, | |
jsCommon | |
); | |
var watchJSStandalone = () => gulp.watch( | |
[ | |
paths.src + paths.scripts.root + 'form/*.js', | |
paths.src + paths.scripts.root + '*.js', | |
], | |
jsStandalone | |
); | |
var webpackConfig = require('./webpack.config.js'); | |
exports.watch = gulp.series( | |
gulp.parallel(jsCommon, jsStandalone), | |
gulp.parallel(css, cssV7), | |
gulp.parallel( | |
watchSass, | |
watchJSCommon, | |
watchJSStandalone, | |
function watchWebpack() { return webpack({...webpackConfig, watch: true},compiler); } | |
)) | |
exports.default = build; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment