webpack-isomorphic-tools: require.context is not a function

I’m getting this error when running webpack-isomorphic-tools' withwebpack`

/<dir>/src/content/index.js:9
[1] var contents = require.context('./', true, /content\.yml$/);
[1]                          ^
[1] 
[1] TypeError: require.context is not a function
[1]     at Object.<anonymous> (index.js:2:28)
[1]     at Module._compile (module.js:425:26)
[1]     at loader (/<dir>/node_modules/babel-register/lib/node.js:134:5)
[1]     at Object.require.extensions.(anonymous function) [as .js] (/<dir>/node_modules/babel-register/lib/node.js:144:7)
[1]     at Module.load (module.js:356:32)
[1]     at Function.Module._load (module.js:313:12)
[1]     at Module.require (module.js:366:17)
[1]     at require (module.js:385:17)
[1]     at Object.<anonymous> (/<dir>/src/selectors/index.js:34:16)
[1]     at Module._compile (module.js:425:26)

How to I circumvent/fix this? the code:

var contents = require.context('./', true, /content\.yml$/);

is used to fetch the data files to an array on runtime. The directory tree looks like this:

├── content
│   ├── index.js
│   ├── 2013
│   │   └── content.yml
│   ├── 2014
│   │   └── content.yml
│   ├── 2015
│   │   └── content.yml
│   └── 2016
│       └── content.yml

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 39 (23 by maintainers)

Commits related to this issue

Most upvoted comments

Well, for example, you could do something like this:

//this file includes all contents indexed by directory name
let contents

if (__CLIENT__)
{
  contents = require.context('./', true, /content\.yml$/);
}
else
{
  const path = require('path')
  const fs = require('fs')
  for (let child of fs.readdirSync(__dirname))
  {
    console.log(child)
    if (fs.statSync(path.join(__dirname, child)).isDirectory())
    {
      contents[path] = require(path.join(__dirname, child, 'content.yml'))
    }
  }
}

__CLIENT__ may be set in your Webpack DefinePlugin, for example.

For anyone who got here from Google or from the To do list:

While looking for a possibility to implement require.context function I currently see no clean way to do it (there is a dirty way in the end of this message).

The require() function is created in the internal/module module to which we have no access https://github.com/nodejs/node/blob/master/lib/module.js#L413 https://github.com/nodejs/node/blob/7c603280024de60329d5da283fb8433420bc6716/lib/internal/module.js#L9

If there was a way to get a hold of that require variable before it is passed to module compilation function then it would be possible to inject a context property into it. Alternatively the makeRequireFunction function could be instrumented if we had a way to import the internal/module module and modify its exports.

The function itself would look like this:

require.context = function(base, scan_subdirectories, regular_expression) {
  const contents = {}

  function read_directory(directory) {
    for (let child of fs.readdirSync(directory)) {
      const full_path = path.join(directory, child)
      if (fs.statSync(full_path).isDirectory()) {
        if (scan_subdirectories) {
          read_directory(full_path)
        }
      } else {
        if (regular_expression && !regular_expression.match(full_path)) {
          continue
        }
        contents[path.relative(base, full_path)] = require(full_path)
      }
  }

  read_directory(base)

  return contents
}

The dirty way I found is:

const original_compile = require('module').prototype._compile
require('module').prototype._compile = function(content, filename)
{
    var preamble = ''

    if (starts_with(content, `'use strict'`) || starts_with(content, `"use strict"`))
    {
        preamble = `"use strict";`
    }

    preamble += `require.context = function() { console.log('require.context code here') };;;` 

    content = preamble + content

    // return value is undefined
    return original_compile.call(this, content, filename)
}

It’s “dirty” because it prepends some code to the require()d module code therefore leaving traces. But it works, i tried (this code has to be executed before the module of interest is require()d).