วิธีโหลดไฟล์ทั้งหมดในไดเร็กทอรีโดยใช้ webpack โดยไม่ต้องใช้งบ


96

ฉันมีไฟล์จาวาสคริปต์จำนวนมากที่แบ่งออกเป็น 4 ไดเรกทอรีย่อยในแอปของฉัน ด้วยความฮึดฮัดฉันคว้าทั้งหมดและรวบรวมเป็นไฟล์เดียว ไฟล์เหล่านี้ไม่มีฟังก์ชัน module.exports

ฉันต้องการใช้ webpack และแบ่งออกเป็น 4 ส่วน ฉันไม่ต้องการเข้าไปด้วยตนเองและต้องการไฟล์ทั้งหมดของฉัน

ฉันต้องการสร้างปลั๊กอินที่ในการคอมไพล์จะเดินไปตามแผนผังไดเร็กทอรีจากนั้นคว้าชื่อไฟล์และพา ธ . js ทั้งหมดจากนั้นต้องการไฟล์ทั้งหมดในไดเร็กทอรีย่อยและเพิ่มลงในเอาต์พุต

ฉันต้องการให้ไฟล์ทั้งหมดในแต่ละไดเร็กทอรีรวบรวมเป็นโมดูลที่ฉันต้องการจากไฟล์จุดเริ่มต้นของฉันหรือรวมไว้ในเนื้อหาที่http://webpack.github.io/docs/plugins.htmlกล่าวถึง

เมื่อเพิ่มไฟล์ใหม่ฉันแค่ต้องการวางลงในไดเร็กทอรีที่ถูกต้องและรู้ว่าจะรวมอยู่ด้วย

มีวิธีดำเนินการกับ webpack หรือปลั๊กอินที่มีคนเขียนไว้ให้ทำสิ่งนี้หรือไม่?

คำตอบ:


119

นี่คือสิ่งที่ฉันทำเพื่อให้บรรลุสิ่งนี้:

function requireAll(r) { r.keys().forEach(r); }
requireAll(require.context('./modules/', true, /\.js$/));

มีวิธีใดบ้างในการระบุว่าจะใช้ตัวโหลดอะไร? กรณีการใช้งานของฉันคือฉันต้องการใช้image-size-loaderสำหรับรูปภาพทั้งหมดเพื่อสร้างตัวยึดตำแหน่งที่มีอัตราส่วนภาพที่ถูกต้อง
bobbaluba

13
คุณช่วยให้ตัวอย่างการใช้งาน webpack.config.js
Rizwan Patel

2
@bobbaluba คุณสามารถระบุตัวโหลดในไฟล์กำหนดค่า: loaders: [ { test: /\.json$/, loader: 'json' } ]. { test: /\.json$/, loader: 'json' }เพิ่มตัวโหลด json สำหรับไฟล์. json ตราบเท่าที่คุณติดตั้งตัวโหลด
Jake

1
โปรดทราบว่าหากคุณพยายามทำตัวให้แห้งโดยเขียนฟังก์ชันที่เรียกร้องrequire.context(...)ให้คุณ (เช่นหากคุณต้องการใช้ทุกอย่างในหลายโฟลเดอร์) webpack จะส่งคำเตือน อาร์กิวเมนต์ที่จะrequire.contextต้องเป็นค่าคงที่เวลาคอมไพล์
Isaac Lyman

4
@Joel npmjs.com/package/require-contextถูกสร้างขึ้นในปี 2017 และคำตอบของฉันคือตั้งแต่ปี 2015 ดังนั้นมันจึงเป็นเรื่องยากที่จะบอกว่ามันจะได้รับการตรงจากที่นั่น นอกจากนี้โปรดทราบว่าrequire-contextเป็นกระดาษห่อหุ้มwebpackและตัวอย่างของมันถูกนำมาจากwebpackเอกสารของที่webpack.js.org/guides/dependency-management/#context-module-apiซึ่งเพิ่มในปี 2559 (ในgithub.com/webpack/ webpack.js.org/commit/… ) หลังจากที่ฉันเขียนคำตอบแล้ว ... บางทีนักเขียนของ webpack อาจได้รับอิทธิพลจากคำตอบของฉัน โปรดทราบว่าพวกเขาขยายให้มีแคช
เฝือก

38

ในไฟล์แอพของฉันฉันได้วางสิ่งที่ต้องการ

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

เอื้อเฟื้อโพสต์นี้: https://github.com/webpack/webpack/issues/118

ตอนนี้กำลังเพิ่มไฟล์ทั้งหมดของฉัน ฉันมีตัวโหลดสำหรับ html และ css และดูเหมือนว่าจะใช้งานได้ดี


27
คืออะไรexprในตัวอย่างนี้?
twiz

2
exprเป็นเส้นทางไปยังไฟล์เดียวภายในโฟลเดอร์บริบท ดังนั้นหากคุณต้องการทำสิ่งนี้ไม่ใช่เพียงเพื่อต้องการไฟล์ html ทั้งหมดสิ่งนี้มีประโยชน์ webpack.github.io/docs/context.html#context-module-api
mkoryak

18
ยังไม่ชัดเจนสำหรับฉันว่าexprอาร์กิวเมนต์พื้นฐานกำลังทำอะไรอยู่ที่นี่แม้หลังจากดูเอกสาร webpack แล้ว "สิ่งนี้ไม่ใช่เพียงเพื่อต้องการไฟล์ html ทั้งหมด" หมายความว่าอย่างไร ขอบคุณ
mikkelrd

3
ผมได้Uncaught ReferenceError: expr ไม่ได้กำหนดไว้ มีคำใบ้เกี่ยวกับเรื่องนี้หรือไม่?
CSchulz

2
ยังไม่มีคำตอบเกี่ยวกับความexprหมายที่นี่
wizulus

5

แผนที่ของไฟล์ทั้งหมดในโฟลเดอร์ล่ะ

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

ทำเช่นนี้:

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, /.*/));

ขอบคุณที่วางตัวอย่างนี้ ฉันใช้แผนที่เพียงแค่คืนค่าที่แต่ละไฟล์ของฉันส่งออก =)
cacoder

1

ตัวอย่างวิธีรับแผนที่ของรูปภาพทั้งหมดในโฟลเดอร์ปัจจุบัน

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));

1

ขออนุโมทนาบุญกับ @splintor (ขอบคุณ)

แต่นี่เป็นเวอร์ชันที่ได้มาของฉันเอง

สิทธิประโยชน์:

  • การส่งออกโมดูลใดบ้างที่รวบรวมภายใต้ไฟล์ {module_name: exports_obj}วัตถุ
    • module_nameสร้างจากชื่อไฟล์
    • ... โดยไม่ต้องขยายและแทนที่เครื่องหมายทับด้วยขีดล่าง (ในกรณีของการสแกนไดเรกทอรีย่อย)
  • เพิ่มความคิดเห็นเพื่อความสะดวกในการปรับแต่ง
    • กล่าวคือคุณอาจไม่ต้องการรวมไฟล์ในไดเร็กทอรีย่อยหากกล่าวว่าไฟล์เหล่านี้จำเป็นต้องใช้ด้วยตนเองสำหรับโมดูลระดับรู

แก้ไข:ถ้าเช่นฉันคุณแน่ใจว่าโมดูลของคุณจะไม่ส่งคืนสิ่งอื่นใดนอกจาก (อย่างน้อยในระดับรูท) ออบเจ็กต์จาวาสคริปต์ทั่วไปคุณยังสามารถ "เมานต์" พวกเขาเพื่อจำลองโครงสร้างไดเร็กทอรีดั้งเดิมของพวกเขาได้ (ดูรหัส (เวอร์ชันลึก) )ในตอนท้าย)

รหัส (เวอร์ชันดั้งเดิม):

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
));

ตัวอย่าง:

ผลลัพธ์ตัวอย่างสำหรับในที่สุดconsole.log(allModules);:

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

แผนผังไดเรกทอรี:

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

รหัส (รุ่นลึก):

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
));

ตัวอย่าง:

ผลลัพธ์ของตัวอย่างก่อนหน้าโดยใช้เวอร์ชันนี้:

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

0

สิ่งนี้ใช้ได้กับฉัน:

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

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

หมายเหตุ: สิ่งนี้อาจต้องการไฟล์. js ใน subdirs ของ. / js/ แบบวนซ้ำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.