Vextor-ltd
@Vextor-ltd
Webdeveloper

Gulp + webpack-stream. Как создать несколько точек входа с созданием одноимённых файлов на выходе?

Есть сборка Gulp + Webpack для сборки js-файлов через плагин webpack-stream.
Возникла необходимость иметь несколько несколько entry point-ов.
Вот пути:
/* source paths, production paths and paths for files we need to watch */
const path = {
    build: {
        /* ... */
        js: 'assets/build/js/',
        css: 'assets/build/css/',
        /* ... */
    },
    src: {
        /* ... */
        js: ['assets/src/js/main.js', 'assets/src/js/main-01-test.js'], // js entry points, string when one, array when several
        style: ['assets/src/style/main.scss', 'assets/src/style/main-01-test.scss'], // scss entry points, string when one, array when several
        /* ... */
    },
    watch: {
        /* ... */
        js: 'assets/src/**/*.js',
        css: 'assets/src/**/*.scss',
        /* ... */
    },
    clean: './assets/build/*'
};


Когда я билдю scss – то никаких проблем, там вебпак не юзается.
И выглядит это так:

// style build
async function css_build() {
    let stylePath = path.src.style;
    if (stylePath.isArray) {
        stylePath.map( file => css_build_file(file) );
    } else {
        css_build_file(stylePath);
    }
}
// inner function to a current scss entry point file
function css_build_file(file) {
    return gulp.src(file) // get only main.scss in which we have some imports
        .pipe(plumber()) // gulp plugins bug tracking
        .pipe(gulpif(devMode, sourcemaps.init())) // initialize source maps
        .pipe(sass()) // scss -> css
        .pipe(autoprefixer({ // add vendor prefixes to CSS
            overrideBrowserslist: ['last 2 versions'], // last two versions recommended
            cascade: false
        }))
        .pipe(gulp.dest(path.build.css)) // build temporary css
        .pipe(rename({ suffix: '.min' })) // add prefixes to the built file
        .pipe(cleanCSS({ level: { 1: { specialComments: 0 } } })) // minify CSS and disable even special comments
        .pipe(gulpif(devMode, sourcemaps.write('./')))  // write source maps
        .pipe(gulp.dest(path.build.css)) // build final css
        .pipe(browserSync.reload({ stream: true })); // browser-sync reload
}


JS делаю вот так:
// js build
async function js_build() {
    let jsPath = path.src.js;
    if (jsPath.isArray) {
        jsPath.map( file => js_build_file(file) );
    } else {
        js_build_file(jsPath);
    }
}
// inner function to a current js entry point file
function js_build_file(file) {
    return gulp.src(file)
        .pipe(webpackStream({
            mode: `${(devMode === true) ? 'development' : 'production'}`, // pass the current mode for webpack
            output: {
                filename: `[name].js`,  // specify just one output file, same name as source
            },
            module: {
                rules: [
                    {
                        test: /\.(js)$/,    // get all js-files
                        exclude: /(node_modules)/, // exclude development modules folder
                        loader: 'babel-loader', // convert ES6 into a backwards compatible version of JS
                        query: {
                            presets: ['@babel/env'] // use babel preset
                        }
                    },
                ]
            },
            optimization: {
                minimize: true,
                minimizer: [new TerserPlugin()],
            },
        })).on('error', function handleError() {
            this.emit('end')
        })
        .pipe(gulp.dest(path.build.js))  // build temporary js
        .pipe(rename({ suffix: '.min' })) // add suffix to the filename
        .pipe(gulp.dest(path.build.js)) // build final js
        .pipe(browserSync.reload({ stream: true })); // browser-sync reload
}


Файл main-01-test.js на билде не создаётся, всё почему-то летит в main.js.
Я ведь прохожусь по массиву, а в функции js_build_file(file) указываю:
output: {
        filename: `[name].js`, 
},


Должен создаться новый файл на выходе и получить название main-01-test.js,
но всё почему-то летит в main.js
Почему? Несколько потоков webpack-stream не может быть? Как исправить?

Спасибо.
  • Вопрос задан
  • 683 просмотра
Решения вопроса 1
Vextor-ltd
@Vextor-ltd Автор вопроса
Webdeveloper
Разобрался.

1) Перебирать массив с файлами не нужно. С этим справляется gulp.src(). Надо просто передать туда массив.

2) Ну и поскольку я прописываю в начале стартер кита все файлы и пути к ним для работы методом gulp.src(), в данном случае Entrypoint-файлы помещаются в массив:
const path = {
    build: {
        /* ... */
        js: 'assets/build/js/',
        /* ... */
    },
    src: {
        /* ... */
        js: ['assets/src/js/main.js', 'assets/src/js/main-01-test.js']
/* ... */


..то внутри функции для js-таска необходимо просто преобразовать этот массив в объект со свойствами, которые представляют из себя имена этих файлов без разрешений, и добавить это свойство в объект Вебпак конфига.
Вот эта функция:

function js_build() {

    let webpackConf = {
        mode: `${(devMode === true) ? 'development' : 'production'}`, // current mode for webpack
        output: {
            filename: `[name].js`,  // the same name as the source
            sourceMapFilename: '[name].map'
        },
        module: {
            rules: [
                {
                    test: /\.(js)$/,    // get all js-files
                    exclude: /(node_modules)/, // exclude development modules folder
                    loader: 'babel-loader', // convert ES6 into a backwards compatible version of JS in older browsers
                    query: {
                        presets: ['@babel/env'] // use babel preset
                    }
                },
            ]
        },
        optimization: {
            minimize: true,
            minimizer: [new TerserPlugin()],
        },
    };

    // convert Gulp array into entry property for Webpack
    let fileName = null;
    let entryObj = {};
    path.src.js.map((filePath) => {
      fileName = filePath.split('/').pop().split('.').slice(0, -1).join('.');
      entryObj[fileName] = filePath;
    });

    // add converted entry property to Webpack    
    webpackConf.entry = entryObj;

    return gulp.src(path.src.js)
        .pipe(webpackStream(webpackConf)).on('error', function handleError() {
            this.emit('end')
        })
        .pipe(gulp.dest(path.build.js))  // build js
        .pipe(rename({ suffix: '.min' })) // add suffix to the filename
        .pipe(gulp.dest(path.build.js)) // build final min js
        .pipe(browserSync.reload({ stream: true })); // browser-sync reload
}

exports.js_build = js_build;


Короче, вот такая вот тема для Галпа с использованием Вебпака для билда js-файлов с несколькими энтрипоинтами. Может кому пригодится :)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы