【发布时间】:2021-10-26 14:15:45
【问题描述】:
我使用 Gulp 的构建时间大约是 90 秒(有时甚至更长),这似乎是非常缓慢的构建时间。我正在使用 Django、Tailwindcss、Gulp、Webpack 和 Docker。我在没有 docker 的情况下尝试了 'npm run dev',花了 41 秒。
在使用 Docker 时如何优化我的 Gulp 配置?
node_1 | ✔ - [Styles] Success!
node_1 | [12:40:43] Finished 'styles' after 49 s
node_1 | [12:40:48] asset index.js 138 KiB [emitted] (name: main) 1 related asset
node_1 |
node_1 | webpack 5.51.1 compiled successfully
node_1 | ✔ - [Scripts] Success!
node_1 | [12:40:49] Finished 'scripts' after 54 s
node_1 | ✔ - [HTML] Success!
node_1 | [12:40:54] Finished 'html' after 59 s
node_1 | [12:41:10] gulp-imagemin: Minified 1 image (saved 11 B - 0.1%)
node_1 | ✔ - [Images] Success!
node_1 | [12:41:10] Finished 'images' after 1.25 min
node_1 | [12:41:10] Finished 'build' after 1.27 min
node_1 | [12:41:17] Using gulpfile /usr/src/app/gulpfile.mjs
node_1 | [12:41:17] Starting 'watch'...
node_1 | [Browsersync] Proxying: http://localhost:8000
node_1 | [Browsersync] Access URLs:
node_1 | -----------------------------------
node_1 | Local: http://localhost:8000
node_1 | External: http://172.18.0.4:8000
node_1 | -----------------------------------
node_1 | UI: http://localhost:3001
node_1 | UI External: http://localhost:3001
node_1 | -----------------------------------
node_1 | [Browsersync] Watching files...
gulpfile
/* eslint-disable import/newline-after-import */
import figures from 'figures';
import imagemin, { gifsicle, mozjpeg, optipng, svgo } from 'gulp-imagemin';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// "require" is not defined with ES6 module, so we define it this way above.
// Now 'require' can be used in the usual way.
// Use import for ES6 modules and require for commonJS.
const gulp = require('gulp');
const autoprefixer = require('autoprefixer');
const browserSync = require('browser-sync').create();
const gulpAutoprefixer = require('gulp-autoprefixer');
const gulpClean = require('gulp-clean');
const gulpColor = require('gulp-color');
const gulpConcat = require('gulp-concat');
const gulpCssnano = require('gulp-cssnano');
const htmlMinimizer = require('gulp-html-minimizer'); // Minify HTML files
const gulpPostcss = require('gulp-postcss');
const gulpSass = require('gulp-sass')(require('sass'));
const gulpSourcemaps = require('gulp-sourcemaps');
const gulpUtil = require('gulp-util');
const purgeCss = require('@fullhuman/postcss-purgecss');
const tailwindCSS = require('tailwindcss');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const isProd = process.env.NODE_ENV === 'production';
const webpackConfig = isProd
? require('./webpack.config.prod')
: require('./webpack.config');
// Config
const options = {
config: {
tailwindjs: './tailwind.config.js',
},
paths: {
src: {
base: './assets',
html: './templates/local',
css: './assets/css',
js: './assets/js',
img: './assets/img',
},
dist: {
base: './dist',
html: './templates/local',
css: './dist/css',
js: './dist/js',
img: './dist/img',
},
build: {
base: './config/static',
html: './templates/production',
css: './config/static/css',
js: './config/static/js',
img: './config/static/img',
},
},
};
const logger = (text, symbol = figures.info, color = 'YELLOW') => {
console.log(gulpColor(`${symbol} - ${text}`, color));
};
const reload = done => {
setTimeout(() => {
browserSync.reload();
}, 1000);
done();
};
gulp.task('clean', () => {
logger('[Cleaning] Cleaning old dist..');
return gulp
.src(
isProd
? [options.paths.build.base, options.paths.build.html]
: options.paths.dist.base,
{
read: false,
allowEmpty: true,
}
)
.pipe(gulpClean())
.on('end', () => logger('[Cleaning] Success!', figures.tick, 'GREEN'))
.on('error', () => logger('[Cleaning] Failed', figures.cross, 'RED'));
});
// Updated gulp pipe: passing webpack in webpack-stream to avoid this issue:
// https://github.com/webpack-contrib/terser-webpack-plugin/issues/335
gulp.task('scripts', () => {
logger('[Scripts] Compiling...');
return gulp
.src(`${options.paths.src.js}/app.js`)
.pipe(webpackStream(webpackConfig, webpack))
.pipe(
isProd
? gulp.dest(options.paths.build.js)
: gulp.dest(options.paths.dist.js)
)
.on('end', () => logger('[Scripts] Success!', figures.tick, 'GREEN'))
.on('error', () => logger('[Scripts] Failed', figures.cross, 'RED'));
});
gulp.task('styles', () => {
logger('[Styles] Compiling...');
return gulp
.src(`${options.paths.src.css}/**/*.scss`)
.pipe(gulpSass().on('error', gulpSass.logError))
.pipe(
gulpPostcss([
tailwindCSS(options.config.tailwindjs),
autoprefixer,
...(isProd
? [
purgeCss({
content: [
`${options.paths.src.html}/**/*.{html}`,
`${options.paths.src.js}/**/*.{js}`,
],
defaultExtractor: content => {
const broadMatches =
content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [];
const innerMatches =
content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || [];
return broadMatches.concat(innerMatches);
},
}),
]
: []),
])
)
.pipe(gulpAutoprefixer())
.pipe(isProd ? gulpSourcemaps.init() : gulpUtil.noop())
.pipe(gulpConcat('style.css'))
.pipe(isProd ? gulpCssnano() : gulpUtil.noop())
.pipe(isProd ? gulpSourcemaps.write('.') : gulpUtil.noop())
.pipe(
isProd
? gulp.dest(options.paths.build.css)
: gulp.dest(options.paths.dist.css)
)
.on('end', () => logger('[Styles] Success!', figures.tick, 'GREEN'))
.on('error', () => logger('[Styles] Failed', figures.cross, 'RED'));
});
gulp.task('images', () => {
logger('[Images] Optimizing...');
return gulp
.src(`${options.paths.src.img}/**/*.*`)
.pipe(
imagemin(
[
gifsicle({ interlaced: true }),
mozjpeg({
quality: 80,
progressive: true,
}),
optipng({ optimizationLevel: 5 }),
svgo({ removeViewBox: true, cleanupIDs: false }),
],
{
silent: false,
}
)
)
.pipe(
isProd
? gulp.dest(options.paths.build.img)
: gulp.dest(options.paths.dist.img)
)
.on('end', () => logger('[Images] Success!', figures.tick, 'GREEN'))
.on('error', () => logger('[Images] Failed', figures.cross, 'RED'));
});
gulp.task('html', () => {
logger('[HTML] Optimizing...');
return gulp
.src(`${options.paths.src.html}/**/*.html`)
.pipe(
isProd
? htmlMinimizer({
collapseWhitespace: true,
removeComments: true,
continueOnParseError: true,
html5: true,
// minifyJS: true,
// minifyCSS: true,
})
: gulpUtil.noop()
)
.pipe(
isProd
? gulp.dest(options.paths.build.html)
: gulp.dest(options.paths.dist.html)
)
.on('end', () => logger('[HTML] Success!', figures.tick, 'GREEN'))
.on('error', () => logger('[HTML] Failed', figures.cross, 'RED'));
});
gulp.task('watch', () => {
browserSync.init({
// The hostname is the name of your service in docker-compose.yml.
// The port is what's defined in your Dockerfile.
hostname: 'django',
port: 8000,
proxy: 'localhost:8000',
open: false,
files: ['./dist', './templates/local'],
});
gulp
.watch(`${options.paths.src.js}/**/*.*`, gulp.series('scripts'))
.on('change', reload);
gulp
.watch(`${options.paths.src.css}/**/*.*`, gulp.series('styles'))
.on('change', reload);
gulp
.watch(`${options.paths.src.img}/**/*.*`, gulp.series('images'))
.on('change', reload);
gulp
.watch(`${options.paths.src.html}/**/*.*`, gulp.series('html'))
.on('change', reload);
});
gulp.task(
'build',
gulp.series('clean', gulp.parallel('scripts', 'styles', 'images', 'html'))
);
webpack.config.js
module.exports = {
mode: 'development',
entry: ['./assets/js/app.js'],
output: {
// eslint-disable-next-line no-path-concat
path: `${__dirname}/dist/js`,
filename: 'index.js',
},
devtool: false,
module: {
rules: [
{
test: /\.js$/,
resolve: {
fullySpecified: false,
},
exclude: /node_modules\/(?!app-js)/,
use: {
loader: 'babel-loader',
},
},
],
},
};
Dockerfile
FROM node:12.22-buster-slim
RUN npm i npm@latest -g
WORKDIR /usr/src
COPY ./app/package*.json ./
RUN apt-get update && apt-get install -y --no-install-recommends \
autoconf \
automake \
g++ \
libpng-dev \
make\
nasm \
-y wget \
&& wget -q -O /tmp/libpng12.deb http://mirrors.kernel.org/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.54-1ubuntu1_amd64.deb \
&& dpkg -i /tmp/libpng12.deb \
&& rm /tmp/libpng12.deb \
&& npm install --no-optional && npm cache clean --force \
npm install -g gulp \
&& npm install gulp
ENV PATH /usr/src/node_modules/.bin/:$PATH
WORKDIR /usr/src/app
COPY . .
docker-compose.yml
version: '3'
volumes:
local_postgres_data: {}
local_postgres_data_backups: {}
notused:
services:
postgres:
build:
context: .
dockerfile: ./app/docker/postgres/Dockerfile
image: webapp_prodcution_postgres
volumes:
- local_postgres_data:/var/lib/postgresql/data:Z
- local_postgres_data_backups:/backups:z
env_file:
- ./app/.envs/.local/.env
django:
image: webapp_local_django
build:
context: .
dockerfile: ./app/docker/django/Dockerfile
volumes:
- ./app/:/usr/src/app/
command: /usr/src/app/docker/django/start_dev
ports:
- 8000:8000
env_file:
- ./app/.envs/.local/.env
depends_on:
- postgres
node:
image: webapp_local_node
build:
context: .
dockerfile: ./app/docker/node/Dockerfile
depends_on:
- django
volumes:
- ./app/:/usr/src/app/
- notused:/usr/src/app/node_modules/
command: bash -c "rm -rf /usr/src/app/node_modules/* && npm run dev"
ports:
- '3000:3000'
package.json
{
"private": true,
"main": "gulpfile.mjs",
"scripts": {
"dev": "gulp build && gulp watch",
"build": "cross-env NODE_ENV=production gulp build",
"preinstall": "npx npm-force-resolutions"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/eslint-parser": "^7.15.0",
"@babel/preset-env": "^7.15.0",
"@fullhuman/postcss-purgecss": "^4.0.3",
"@tailwindcss/aspect-ratio": "^0.2.1",
"@tailwindcss/forms": "^0.3.3",
"autoprefixer": "^10.3.1",
"babel-loader": "^8.2.2",
"browser-sync": "^2.27.5",
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-node": "^4.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.24.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0",
"figures": "^4.0.0",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^8.0.0",
"gulp-babel": "^8.0.0",
"gulp-clean": "^0.4.0",
"gulp-cli": "^2.3.0",
"gulp-color": "0.0.2",
"gulp-concat": "^2.6.1",
"gulp-cssnano": "^2.1.3",
"gulp-html-minimizer": "^2.0.1",
"gulp-imagemin": "^8.0.0",
"gulp-postcss": "^9.0.0",
"gulp-sass": "^5.0.0",
"gulp-sourcemaps": "^3.0.0",
"gulp-util": "^3.0.8",
"postcss": "^8.3.6",
"prettier": "^2.3.2",
"sass": "^1.37.5",
"tailwindcss": "^2.2.7",
"webpack": "^5.50.0",
"webpack-stream": "^6.1.2"
},
"dependencies": {
"alpinejs": "^3.2.4",
"aos": "^3.0.0-beta.6",
"focus-handling": "^1.0.0",
"sticky-js": "^1.3.0"
},
"engines": {
"node": ">=12.22"
},
"resolutions": {
"glob-parent": "6.0.1",
"trim-newlines": "4.0.2",
"yargs-parser": "20.2.9",
"js-yaml": "4.1.0"
}
}
【问题讨论】:
-
你能展示一下你的 Dockerfile 是什么样子的吗?
-
@Stefano 我更新了我的问题并添加了有关 Docker 的更多信息。
标签: node.js docker webpack gulp