Page MenuHomeSoftware Heritage

webpack.config.development.js
No OneTemporary

webpack.config.development.js

/**
* Copyright (C) 2018-2022 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
*/
// webpack configuration for compiling static assets in development mode
// import required node modules and webpack plugins
const chalk = require('chalk');
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
const RobotstxtPlugin = require('robotstxt-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin').CleanWebpackPlugin;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FixSwhSourceMapsPlugin = require('./webpack-plugins/fix-swh-source-maps-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const GenerateWebLabelsPlugin = require('./webpack-plugins/generate-weblabels-webpack-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const DumpHighlightjsLanguagesDataPlugin = require('./webpack-plugins/dump-highlightjs-languages-data-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
// are we running webpack-dev-server ?
const isDevServer = process.argv.find(v => v.includes('serve')) !== undefined;
// webpack-dev-server configuration
const devServerPort = 3000;
const devServerPublicPath = 'http://localhost:' + devServerPort + '/static/';
// set publicPath according if we are using webpack-dev-server to serve
// our assets or not
const publicPath = isDevServer ? devServerPublicPath : '/static/';
const nodeModules = path.resolve(__dirname, '../../node_modules/');
// collect all bundles we want to produce with webpack,
// bundles will be generated by scanning swh-web django applications:
// * if swh/web/<app>/assets/index.js exists, bundle <app> is generated
// * if swh/web/<app>/assets/<bundle>/index.js exists, bundle <bundle> is generated
var bundles = {};
const appsDir = path.join(__dirname, '../../swh/web');
fs.readdirSync(appsDir).forEach(app => {
const appAssetsDir = path.join(appsDir, app, 'assets');
if (fs.existsSync(appAssetsDir)) {
const appAssetsIndex = path.join(appAssetsDir, 'index.js');
if (fs.existsSync(appAssetsIndex)) {
bundles[app] = [path.join(app, 'assets', 'index.js')];
} else {
fs.readdirSync(appAssetsDir).forEach(appBundle => {
const appBundleIndex = path.join(appAssetsDir, appBundle, 'index.js');
if (fs.existsSync(appBundleIndex)) {
bundles[appBundle] = [path.join(app, 'assets', appBundle, 'index.js')];
}
});
}
}
});
// common loaders for css related assets (css, sass)
const cssLoaders = [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: !isDevServer
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: !isDevServer,
postcssOptions: {
plugins: [
// lint swh-web stylesheets
['stylelint', {
'config': {
'extends': 'stylelint-config-standard',
'rules': {
'indentation': 4,
'font-family-no-missing-generic-family-keyword': null,
'no-descending-specificity': null,
'selector-class-pattern': null
},
'ignoreFiles': ['node_modules/**/*.css',
'assets/src/thirdparty/**/*.css']
}
}],
// automatically add vendor prefixes to css rules
'autoprefixer',
'postcss-normalize',
['postcss-reporter', {
clearReportedMessages: true
}]
]
}
}
}
];
// webpack development configuration
module.exports = {
// use caching to speedup incremental builds
cache: {
type: 'filesystem'
},
// set mode to development
mode: 'development',
// workaround for https://github.com/webpack/webpack-dev-server/issues/2758
target: process.env.NODE_ENV === 'development' ? 'web' : 'browserslist',
// use eval source maps when using webpack-dev-server for quick debugging,
// otherwise generate source map files (more expensive)
devtool: isDevServer ? 'eval' : 'source-map',
// webpack-dev-server configuration
devServer: {
client: {
logging: 'warn',
overlay: {
warnings: true,
errors: true
},
progress: true
},
devMiddleware: {
publicPath: devServerPublicPath,
stats: 'errors-only'
},
host: '0.0.0.0',
port: devServerPort,
// enable to serve static assets not managed by webpack
static: {
directory: path.resolve('./'),
watch: false
},
// we do not use hot reloading here (as a framework like React needs to be used in order to fully benefit from that feature)
// and prefer to fully reload the frontend application in the browser instead
hot: false,
historyApiFallback: true,
headers: {
'Access-Control-Allow-Origin': '*'
},
watchFiles: {
paths: ['assets/**/*', 'static/**/*', 'swh/web/**/*'],
options: {
ignored: /.*.sqlite3.*/
}
}
},
// set entries to the bundles we want to produce
entry: bundles,
// assets output configuration
output: {
path: path.resolve('./static/'),
filename: 'js/[name].[contenthash].js',
chunkFilename: 'js/[name].[contenthash].js',
publicPath: publicPath,
// each bundle will be compiled as a umd module with its own namespace
// in order to easily use them in django templates
library: ['swh', '[name]'],
libraryTarget: 'umd'
},
// module resolving configuration
resolve: {
// alias pdfjs to its minified version
alias: {
'pdfjs-dist': 'pdfjs-dist/build/pdf.min.js'
},
// configure base paths for resolving modules with webpack
modules: [
'node_modules',
path.resolve(__dirname, '../src'),
path.resolve(__dirname, '../../swh/web')
]
},
stats: 'errors-warnings',
snapshot: {
// fix webpack warning related to missing package.json file
managedPaths: [/^highlightjs-/]
},
// module import configuration
module: {
rules: [
{
// Use babel-loader in order to use es6 syntax in js files
// but also advanced js features like async/await syntax.
// All code get transpiled to es5 in order to be executed
// in a large majority of browsers.
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
// use env babel presets to benefit from es6 syntax
['@babel/preset-env', {
// Do not transform es6 module syntax to another module type
// in order to benefit from dead code elimination (aka tree shaking)
// when running webpack in production mode
'loose': true,
'modules': false
}]
],
plugins: [
// use babel transform-runtime plugin in order to use aync/await syntax
['@babel/plugin-transform-runtime', {
'regenerator': true
}],
// use other babel plugins to benefit from advanced js features (es2017)
'@babel/plugin-syntax-dynamic-import'
],
env: {
test: {
plugins: ['istanbul']
}
}
}
}]
},
{
test: /\.ejs$/,
use: [{
loader: 'ejs-compiled-loader',
options: {
htmlmin: true,
htmlminOptions: {
removeComments: true
}
}
}]
},
// expose jquery to the global context as $ and jQuery when importing it
{
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: {
exposes: [
{
globalName: '$',
override: true
},
{
globalName: 'jQuery',
override: true
}
]
}
}]
},
// expose highlightjs to the global context as hljs when importing it
{
test: require.resolve('highlight.js'),
use: [{
loader: 'expose-loader',
options: {
exposes: {
globalName: 'hljs',
override: true
}
}
}]
},
// css import configuration:
// - first process it with postcss
// - then extract it to a dedicated file associated to each bundle
{
test: /\.css$/,
use: cssLoaders
},
// sass import configuration:
// - generate css with sass-loader
// - process it with postcss
// - then extract it to a dedicated file associated to each bundle
{
test: /\.scss$/,
use: cssLoaders.concat([
{
loader: 'sass-loader',
options: {
sourceMap: !isDevServer
}
}
])
},
// web fonts import configuration
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext][query]'
}
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext][query]'
}
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext][query]'
}
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext][query]'
}
}, {
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext][query]'
}
}, {
test: /\.png$/,
type: 'asset/resource',
generator: {
filename: 'img/thirdParty/[name][ext][query]'
}
},
{
test: /\.ya?ml$/,
type: 'json',
use: {
loader: 'yaml-loader',
options: {
asJSON: true
}
}
}
],
// tell webpack to not parse already minified files to speedup build process
noParse: [path.resolve(nodeModules, 'pdfjs-dist/build/pdf.min.js'),
path.resolve(nodeModules, 'mathjax/es5/tex-mml-chtml.js')]
},
// webpack plugins
plugins: [
// cleanup previously generated assets
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['**/*', '!xml', '!xml/*', '!img', '!img/*',
'!img/logos', '!img/logos/*', '!img/icons',
'!img/icons/*', '!json', '!json/*']
}),
// needed in order to use django_webpack_loader
new BundleTracker({
filename: './static/webpack-stats.json'
}),
// for generating the robots.txt file
new RobotstxtPlugin({
policy: [{
userAgent: '*',
disallow: '/api/'
}]
}),
// for extracting all stylesheets in separate css files
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css',
chunkFilename: 'css/[name].[contenthash].css'
}),
// fix generated asset sourcemaps to workaround a Firefox issue
new FixSwhSourceMapsPlugin(),
// define some global variables accessible from js code
new webpack.DefinePlugin({
__STATIC__: JSON.stringify(publicPath)
}),
// needed in order to use bootstrap 4.x
new webpack.ProvidePlugin({
Popper: ['popper.js', 'default'],
Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
Button: 'exports-loader?Button!bootstrap/js/dist/button',
Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel',
Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse',
Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown',
Modal: 'exports-loader?Modal!bootstrap/js/dist/modal',
Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
Util: 'exports-loader?Util!bootstrap/js/dist/util'
}),
// needed in order to use pdf.js
new webpack.IgnorePlugin({resourceRegExp: /^\.\/pdf.worker.js$/}),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(nodeModules, 'pdfjs-dist/build/pdf.worker.min.js'),
to: path.resolve(__dirname, '../../static/js/')
},
{
from: path.resolve(nodeModules, 'mathjax/es5/output/chtml/fonts/woff-v2/**'),
to: path.resolve(__dirname, '../../static/fonts/[name][ext]')
}
]
}),
new GenerateWebLabelsPlugin({
outputType: 'json',
exclude: ['mini-css-extract-plugin',
'bootstrap-loader'],
srcReplace: {
'./node_modules/pdfjs-dist/build/pdf.min.js':
'./node_modules/pdfjs-dist/build/pdf.js',
'./node_modules/admin-lte/dist/js/adminlte.min.js':
'./node_modules/admin-lte/dist/js/adminlte.js'
},
licenseOverride: {
'./assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js': {
'spdxLicenseExpression': 'GPL-3.0',
'licenseFilePath': './assets/src/thirdparty/jquery.tabSlideOut/LICENSE'
},
'./node_modules/highlightjs-chapel/dist/chapel.min.js': {
'spdxLicenseExpression': 'BSD-3-Clause',
'licenseFilePath': './node_modules/highlightjs-chapel/LICENSE'
},
'./node_modules/highlightjs-mirc/mirc.js': {
'spdxLicenseExpression': 'MIT',
'licenseFilePath': './node_modules/highlightjs-mirc/LICENSE'
},
'./node_modules/highlightjs-never/dist/never.min.js': {
'spdxLicenseExpression': 'MIT',
'licenseFilePath': './node_modules/highlightjs-never/LICENSE'
}
},
additionalScripts: Object.assign(
{
'js/pdf.worker.min.js': [
{
'id': 'pdfjs-dist/build/pdf.worker.js',
'path': './node_modules/pdfjs-dist/build/pdf.worker.js',
'spdxLicenseExpression': 'Apache-2.0',
'licenseFilePath': './node_modules/pdfjs-dist/LICENSE'
}
],
'/jsreverse/': [
{
'id': 'jsreverse',
'path': '/jsreverse/',
'spdxLicenseExpression': 'AGPL-3.0-or-later',
'licenseFilePath': './LICENSE'
}
],
'https://piwik.inria.fr/matomo.js': [
{
'id': 'matomo.js',
'path': 'https://github.com/matomo-org/matomo/blob/master/js/piwik.js',
'spdxLicenseExpression': 'BSD-3-Clause',
'licenseFilePath': 'https://github.com/matomo-org/matomo/blob/master/js/LICENSE.txt'
}
]
}
)
}),
new ProgressBarPlugin({
format: chalk.cyan.bold('webpack build of swh-web assets') + ' [:bar] ' + chalk.green.bold(':percent') + ' (:elapsed seconds)',
width: 50
}),
new DumpHighlightjsLanguagesDataPlugin(),
// Process all js files with eslint for consistent code style
// and avoid bad js development practices.
new ESLintPlugin({
overrideConfigFile: path.join(__dirname, '.eslintrc'),
ignorePath: path.join(__dirname, '.eslintignore'),
cache: true,
emitWarning: true
})
],
// webpack optimizations
optimization: {
// ensure the vendors bundle gets emitted in a single chunk
splitChunks: {
cacheGroups: {
defaultVendors: {
test: 'vendors',
chunks: 'all',
name: 'vendors',
enforce: true
}
}
}
},
// disable webpack warnings about bundle sizes
performance: {
hints: false
}
};

File Metadata

Mime Type
text/plain
Expires
Sat, Jun 21, 5:56 PM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3236838

Event Timeline