Cara memuat semua file dalam direktori menggunakan webpack tanpa pernyataan memerlukan

96

Saya memiliki sejumlah besar file javascript yang dibagi menjadi 4 subdirektori di aplikasi saya. Dengan mendengus saya mengambil semuanya dan mengkompilasinya menjadi satu file. File-file ini tidak memiliki fungsi module.exports.

Saya ingin menggunakan webpack dan membaginya menjadi 4 bagian. Saya tidak ingin masuk secara manual dan memerlukan semua file saya.

Saya ingin membuat sebuah plugin yang saat kompilasi berjalan di pohon direktori, lalu mengambil semua nama dan jalur file .js, kemudian membutuhkan semua file di sub direktori dan menambahkannya ke output.

Saya ingin semua file di setiap direktori dikompilasi menjadi modul yang kemudian dapat saya perlukan dari file titik masuk saya, atau disertakan dalam aset yang disebutkan oleh http://webpack.github.io/docs/plugins.html .

Saat menambahkan file baru, saya hanya ingin meletakkannya di direktori yang benar dan tahu itu akan dimasukkan.

Apakah ada cara untuk melakukan ini dengan webpack atau plugin yang ditulis seseorang untuk melakukan ini?

AyamFur
sumber

Jawaban:

119

Inilah yang saya lakukan untuk mencapai ini:

function requireAll(r) { r.keys().forEach(r); }
requireAll(require.context('./modules/', true, /\.js$/));
splintor
sumber
Apakah ada cara untuk menentukan loader apa yang akan digunakan? Kasus penggunaan saya adalah saya ingin menggunakan image-size-loaderuntuk semua gambar untuk membuat placeholder dengan rasio aspek yang benar.
bobbaluba
13
dapatkah Anda memberi Anda contoh webpack.config.js yang berfungsi
Rizwan Patel
2
@bobbaluba, Anda dapat menentukan loader dalam file konfigurasi: loaders: [ { test: /\.json$/, loader: 'json' } ]. { test: /\.json$/, loader: 'json' }menambahkan json loader untuk file .json, selama Anda telah menginstal loader tersebut.
Jake
1
Perlu diingat bahwa jika Anda mencoba KERING di sini dengan menulis fungsi yang memanggil require.context(...)Anda (misalnya jika Anda mencoba meminta semuanya di beberapa folder), webpack akan memberikan peringatan. Argumen require.contextharus berupa konstanta waktu kompilasi.
Isaac Lyman
4
@ Joel npmjs.com/package/require-context diciptakan pada tahun 2017 dan jawaban saya adalah dari tahun 2015, sehingga sulit untuk mengatakan itu diambil langsung dari sana. Perhatikan juga itu require-contextpembungkus webpack, dan sampelnya diambil dari webpackdokumentasi di webpack.js.org/guides/dependency-management/#context-module-api - yang ditambahkan pada 2016 (di github.com/webpack/ webpack.js.org/commit/… ), juga setelah saya menulis jawaban saya ... Mungkin penulis webpack terpengaruh oleh jawaban saya. Perhatikan bahwa mereka memperluasnya untuk memiliki cache.
splintor
38

Di file aplikasi saya, saya akhirnya memasukkan persyaratan

require.context(
  "./common", // context folder
  true, // include subdirectories
  /.*/ // RegExp
)("./" + expr + "")

milik posting ini: https://github.com/webpack/webpack/issues/118

Sekarang menambahkan semua file saya. Saya memiliki loader untuk html dan css dan tampaknya berfungsi dengan baik.

AyamFur
sumber
27
Apa exprdalam contoh ini?
twiz
2
expradalah jalur ke satu file dalam folder konteks. jadi jika Anda perlu melakukan ini tidak hanya karena membutuhkan semua file html, ini berguna. webpack.github.io/docs/context.html#context-module-api
mkoryak
18
masih belum jelas bagi saya apa yang dilakukan exprargumen berbasis di sini bahkan setelah melihat dokumen webpack. apa artinya "melakukan ini tidak hanya untuk meminta semua file html"? terima kasih
mikkelrd
3
Saya mendapat Uncaught ReferenceError: expr tidak ditentukan . Ada petunjuk tentang itu?
CSchulz
2
Masih belum ada jawaban tentang apa exprartinya di sini
wizulus
5

Bagaimana dengan peta semua file dalam satu folder?

// { 
//   './image1.png':  'data:image/png;base64,iVBORw0KGgoAAAANS',
//   './image2.png':  'data:image/png;base64,iVBP7aCASUUASf892',
// }

Melakukan hal ini:

const allFiles = (ctx => {
    let keys = ctx.keys();
    let values = keys.map(ctx);
    return keys.reduce((o, k, i) => { o[k] = values[i]; return o; }, {});
})(require.context('./path/to/folder', true, /.*/));
Steven de Salas
sumber
Terima kasih telah memberikan contoh ini. Saya menggunakan peta hanya mengembalikan nilai yang setiap file saya diekspor =).
cacoder
1

Contoh bagaimana mendapatkan peta dari semua gambar di folder saat ini.

const IMAGES_REGEX = /\.(png|gif|ico|jpg|jpeg)$/;

function mapFiles(context) {
  const keys = context.keys();
  const values = keys.map(context);
  return keys.reduce((accumulator, key, index) => ({
    ...accumulator,
    [key]: values[index],
  }), {});
}

const allImages = mapFiles(require.context('./', true, IMAGES_REGEX));
Alex K
sumber
1

Semua manfaat untuk @splintor (terima kasih).

Tapi ini dia versi turunan saya sendiri.

Manfaat:

  • Ekspor modul apa yang dikumpulkan di bawah {module_name: exports_obj}objek.
    • module_name dibangun dari nama filenya.
    • ... tanpa ekstensi dan mengganti garis miring dengan garis bawah (untuk pemindaian subdirektori).
  • Menambahkan komentar untuk memudahkan penyesuaian.
    • Yaitu Anda mungkin ingin tidak menyertakan file dalam subdirektori jika, katakanlah, file tersebut ada di sana secara manual diperlukan untuk modul tingkat root .

EDIT: Jika, seperti saya, Anda yakin modul Anda tidak akan mengembalikan apa pun selain (setidaknya di tingkat root) objek javascript biasa, Anda juga dapat "memasang" modul tersebut mereplikasi struktur direktori aslinya (lihat Kode (Versi Dalam) ) di bagian akhir).

Kode (Versi Asli):

function requireAll(r) {
    return Object.fromEntries(
        r.keys().map(function(mpath, ...args) {
            const result =  r(mpath, ...args);
            const name = mpath
                .replace(/(?:^[.\/]*\/|\.[^.]+$)/g, '') // Trim
                .replace(/\//g, '_') // Relace '/'s by '_'s
            ;
            return [name, result];
        })
    );
};
const allModules = requireAll(require.context(
    // Any kind of variables cannot be used here
    '@models'  // (Webpack based) path
    , true     // Use subdirectories
    , /\.js$/  // File name pattern
));

Contoh:

Output sampel untuk akhirnya console.log(allModules);:

{
  main: { title: 'Webpack Express Playground' },
  views_home: {
    greeting: 'Welcome to Something!!',
    title: 'Webpack Express Playground'
  }
}

Pohon direktori:

models
├── main.js
└── views
    └── home.js

Kode (Versi Dalam):

function jsonSet(target, path, value) {
    let current = target;
    path = [...path]; // Detach
    const item = path.pop();
    path.forEach(function(key) {
        (current[key] || (current[key] = {}));
        current = current[key];
    });
    current[item] = value;
    return target;
};
function requireAll(r) {
    const gather = {};
    r.keys().forEach(function(mpath, ...args) {
        const result =  r(mpath, ...args);
        const path = mpath
            .replace(/(?:^[.\/]*\/|\.[^.]+$)/g, '') // Trim
            .split('/')
        ;
        jsonSet(gather, path, result);
    });
    return gather;
};
const models = requireAll(require.context(
    // Any kind of variables cannot be used here
    '@models'  // (Webpack based) path
    , true     // Use subdirectories
    , /\.js$/  // File name pattern
));

Contoh:

Hasil dari contoh sebelumnya menggunakan versi ini:

{
  main: { title: 'Webpack Express Playground' },
  views: {
    home: {
      greeting: 'Welcome to Something!!',
      title: 'Webpack Express Playground'
    }
  }
}
minuman beralkohol
sumber
0

ini berhasil untuk saya:

function requireAll(r) { r.keys().forEach(r); } 

requireAll(require.context('./js/', true, /\.js$/));

CATATAN: ini membutuhkan file .js dalam subdir dari ./js/ secara rekursif.

jack panjang
sumber