Cách tải tất cả các tệp trong thư mục bằng cách sử dụng webpack mà không cần câu lệnh yêu cầu


95

Tôi có một lượng lớn tệp javascript được chia thành 4 thư mục con trong ứng dụng của mình. Trong cơn giận dữ, tôi lấy tất cả chúng và biên dịch chúng thành một tệp. Các tệp này không có chức năng module.exports.

Tôi muốn sử dụng webpack và chia nó thành 4 phần. Tôi không muốn truy cập thủ công và yêu cầu tất cả các tệp của mình.

Tôi muốn tạo một plugin khi biên dịch sẽ đi qua các cây thư mục, sau đó lấy tất cả các tên và đường dẫn tệp .js, sau đó yêu cầu tất cả các tệp trong các thư mục con và thêm nó vào đầu ra.

Tôi muốn tất cả các tệp trong mỗi thư mục được biên dịch thành một mô-đun mà sau đó tôi có thể yêu cầu từ tệp điểm nhập của mình hoặc đưa vào nội dung mà http://webpack.github.io/docs/plugins.html đề cập.

Khi thêm một tệp mới, tôi chỉ muốn thả nó vào đúng thư mục và biết rằng nó sẽ được đưa vào.

Có cách nào để làm điều này với webpack hoặc một plugin mà ai đó đã viết để làm điều này không?

Câu trả lời:


119

Đây là những gì tôi đã làm để đạt được điều này:

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

Có cách nào để chỉ định những gì trình tải để sử dụng? Trường hợp sử dụng của tôi là tôi muốn sử dụng image-size-loadercho tất cả các hình ảnh để tạo trình giữ chỗ với tỷ lệ khung hình chính xác.
bobbaluba

13
bạn có thể cung cấp cho bạn làm việc webpack.config.js mẫu
Rizwan Patel

2
@bobbaluba, bạn có thể chỉ định các bộ nạp trong tập tin cấu hình: loaders: [ { test: /\.json$/, loader: 'json' } ]. { test: /\.json$/, loader: 'json' }thêm trình tải json cho các tệp .json, miễn là bạn đã cài đặt trình tải.
Jake

1
Hãy nhớ rằng nếu bạn cố gắng trở nên KHÔ ở đây bằng cách viết một hàm gọi require.context(...)cho bạn (ví dụ: nếu bạn đang cố gắng yêu cầu mọi thứ trong một số thư mục), webpack sẽ đưa ra cảnh báo. Các đối số require.contextphải là hằng số thời gian biên dịch.
Isaac Lyman

3
@Joel npmjs.com/package/require-context đã được tạo ra vào năm 2017 và câu trả lời của tôi là từ năm 2015, vì vậy thật khó để nói rằng nó được lấy thẳng từ đó. Cũng lưu ý rằng đó require-contextlà một trình bao bọc xung quanh webpackvà mẫu của nó được lấy từ webpacktài liệu của webpack.js.org/guides/dependency-management/#context-module-api - được thêm vào năm 2016 (trong github.com/webpack/ webpack.js.org/commit/… ), cũng như sau khi tôi viết câu trả lời của mình… Có lẽ những người viết webpack đã bị ảnh hưởng bởi câu trả lời của tôi. Lưu ý rằng họ đã mở rộng nó để có bộ nhớ cache.
splintor

38

Trong tệp ứng dụng của tôi, tôi đã đặt yêu cầu

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

lịch sự của bài đăng này: https://github.com/webpack/webpack/issues/118

Nó hiện đang thêm tất cả các tệp của tôi. Tôi có một trình tải cho html và css và nó có vẻ hoạt động tốt.


27
Là gì exprtrong ví dụ này?
twiz

2
exprlà một đường dẫn đến một tệp trong thư mục ngữ cảnh. vì vậy nếu bạn cần làm điều này không chỉ vì yêu cầu tất cả các tệp html, điều này rất hữu ích. webpack.github.io/docs/context.html#context-module-api
mkoryak

18
Tôi vẫn chưa rõ exprđối số dựa trên đang làm gì ở đây ngay cả sau khi xem các tài liệu về webpack. "Làm điều này không chỉ để yêu cầu tất cả các tệp html" nghĩa là gì? cảm ơn bạn
mikkelrd

3
Tôi nhận được Uncaught ReferenceError: expr không được xác định . Bất kỳ gợi ý về điều đó?
CSchulz

2
Vẫn không có câu trả lời về những gì exprcó nghĩa là ở đây
wizulus

5

Làm thế nào về một bản đồ của tất cả các tệp trong một thư mục?

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

Làm cái này:

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

Cảm ơn bạn đã bỏ ví dụ này. Tôi đã sử dụng bản đồ chỉ đơn giản là trả về giá trị mà mỗi tệp của tôi đã xuất ra =).
nhớ đệm,

1

Ví dụ về cách lấy bản đồ của tất cả các hình ảnh trong thư mục hiện tại.

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

Tất cả các giá trị cho @splintor (cảm ơn).

Nhưng đây là phiên bản có nguồn gốc của riêng tôi.

Những lợi ích:

  • Những gì mô-đun xuất được tập hợp dưới một {module_name: exports_obj}đối tượng.
    • module_name được xây dựng từ tên tệp của nó.
    • ... không có phần mở rộng và thay thế dấu gạch chéo bằng dấu gạch dưới (trong trường hợp quét thư mục con).
  • Đã thêm nhận xét để dễ dàng tùy chỉnh.
    • Tức là bạn có thể không muốn bao gồm các tệp trong các thư mục con nếu chúng ở đó được yêu cầu thủ công cho các mô-đun cấp gốc .

CHỈNH SỬA: Nếu, giống như tôi, bạn chắc chắn rằng các mô-đun của mình sẽ không trả về bất cứ thứ gì khác ngoài (ít nhất là ở cấp cơ sở) một đối tượng javascript thông thường, bạn cũng có thể "gắn kết" chúng sao chép cấu trúc thư mục gốc của chúng (xem Mã (Phiên bản sâu) ) ở cuối).

Mã (Phiên bản gốc):

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

Thí dụ:

Đầu ra mẫu cho cuối cùng console.log(allModules);:

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

Cây thư mục:

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

Mã (Phiên bản sâu):

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

Thí dụ:

Kết quả của ví dụ trước sử dụng phiên bản này:

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

0

cái này phù hợp với tôi:

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

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

LƯU Ý: điều này có thể yêu cầu tệp .js trong các thứ tự con của ./js/ một cách đệ quy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.