Cheerio: How is current support for react-native?

Created on 25 Mar 2018  路  21Comments  路  Source: cheeriojs/cheerio

I'm following https://github.com/cheeriojs/cheerio/issues/1058 and I discovered https://github.com/oyyd/cheerio-without-node-native which works but is a fork.

I then tried to install events, stream and utils as mentioned, and also had to install buffer. I now get

undefined is not an object (evaluating superCtor.prototype)

https://imgur.com/a/VSukm

Most helpful comment

I was trying to get around #1058 and I found a solution but it involves the original cheerio module rather than the fork

$ npm i [email protected]
$ npm i events stream buffer

I found the solution at https://www.jianshu.com/p/ddf574337c47 , you have to translate the page as its in foreign language.

 const cheerio = require("cheerio"); 
 let $ = cheerio.load('<h2 class="title">Hello world</h2>')
 console.log($("h2").text());

the above code works smooth.
but,

const response = fetch('http://github.com')
const $ = cheerio.load(response.text())
gives error Can't find variable: buffer

All 21 comments

I've run into the same issue as above. Is this something that will ever be fixed? It seems like a dependency issue and I'm unsure how difficult it would be to provide support for react native dependencies.

PRs welcome :)

The only thing I had to do was cut out the streaming related exports at the bottom of the parser5 module's index.js for this to work in RN (since I'm not using them). I'm doing that automatically after install via https://github.com/ds300/patch-package

The only thing I had to do was cut out the streaming related exports at the bottom of the parser5 module's index.js for this to work in RN (since I'm not using them). I'm doing that automatically after install via https://github.com/ds300/patch-package

I got all the way to node_modules/parse5/lib/index.js (i had to npm install util and utils), but I couldn't find the 'streaming related exports'. There is an index.d.ts file with an "export class serializerstream extends stream.readable" at the very bottom. After commenting out that section, I cannot run patch-package, is says "patch-package requires git". I ran it anyway, and get an: undefined is not a function (evaluating '_iterator2typeof Symbol === "function"? symbol.iterator: "@@iterator"').

what should I do!?

npm: 6.5.2
cheerio-without-node-native: 1.0.0-rc.2
react: 16.5.0
react-native: 0.57.3
image

The only thing I had to do was cut out the streaming related exports at the bottom of the parser5 module's index.js for this to work in RN (since I'm not using them). I'm doing that automatically after install via https://github.com/ds300/patch-package

I got all the way to node_modules/parse5/lib/index.js (i had to npm install util and utils), but I couldn't find the 'streaming related exports'. There is an index.d.ts file with an "export class serializerstream extends stream.readable" at the very bottom. After commenting out that section, I cannot run patch-package, is says "patch-package requires git". I ran it anyway, and get an: undefined is not a function (evaluating '_iterator2typeof Symbol === "function"? symbol.iterator: "@@iterator"').

what should I do!?

npm: 6.5.2
cheerio-without-node-native: 1.0.0-rc.2
react: 16.5.0
react-native: 0.57.3
image

I suggest you give up this idea, js is very inefficient, parsing html in RN will cause UI to be stuck, then I tried react-native-threads, although the UI is not stuck, but the waiting time will exceed the user's patient.
Now I use flutter instead of RN, which works well.

I got all the way to node_modules/parse5/lib/index.js (i had to npm install util and utils), but I couldn't find the 'streaming related exports'.

what should I do!?

@jmasaki24 - this is the change I made to parse5 via patch-package: https://gist.github.com/liamjones/ae7f6f6ae6139fd4a8931f43a052b517

I was trying to get around #1058 and I found a solution but it involves the original cheerio module rather than the fork

$ npm i [email protected]
$ npm i events stream buffer

I found the solution at https://www.jianshu.com/p/ddf574337c47 , you have to translate the page as its in foreign language.

 const cheerio = require("cheerio"); 
 let $ = cheerio.load('<h2 class="title">Hello world</h2>')
 console.log($("h2").text());

the above code works smooth.
but,

const response = fetch('http://github.com')
const $ = cheerio.load(response.text())
gives error Can't find variable: buffer

I was trying to get around #1058 and I found a solution but it involves the original cheerio module rather than the fork

$ npm i [email protected]
$ npm i events stream buffer

I found the solution at https://www.jianshu.com/p/ddf574337c47 , you have to translate the page as its in foreign language.

 const cheerio = require("cheerio"); 
 let $ = cheerio.load('<h2 class="title">Hello world</h2>')
 console.log($("h2").text());

the above code works smooth.
but,

const response = fetch('http://github.com')
const $ = cheerio.load(response.text())
gives error Can't find variable: buffer

What's funny is that i did all as in that guide. And the only way all worked is when i debug project through the IDE VSCode. Otherwise all the time getting same error. Release version not helped too.

I couldn't get cheerio to work in react-native, so I searched for something else for weeks and came across this comment in reddit https://www.reddit.com/r/reactnative/comments/9b08oj/a_frustrated_developer/e4zzsrb/. u/heo5981 suggested https://github.com/ashi009/node-fast-html-parser and was also kind enough to show me an example on how to parse the HTML with it. If anyone is interested, I can add an example.

I couldn't get cheerio to work in react-native, so I searched for something else for weeks and came across this comment in reddit https://www.reddit.com/r/reactnative/comments/9b08oj/a_frustrated_developer/e4zzsrb/. u/heo5981 suggested https://github.com/ashi009/node-fast-html-parser and was also kind enough to show me an example on how to parse the HTML with it. If anyone is interested, I can add an example.

I replaced cheeriowith cheerio-without-node-native and all working fine now.

cheerio-without-node-native is kinda abandonware at this point, I'm the creator of link-preview-js and I'm getting security warnings, it would be nice to know if there is a path forward here

I couldn't get cheerio to work in react-native, so I searched for something else for weeks and came across this comment in reddit https://www.reddit.com/r/reactnative/comments/9b08oj/a_frustrated_developer/e4zzsrb/. u/heo5981 suggested https://github.com/ashi009/node-fast-html-parser and was also kind enough to show me an example on how to parse the HTML with it. If anyone is interested, I can add an example.

I replaced cheeriowith cheerio-without-node-native and all working fine now.

UPDATE: after I upgrade to react-native 0.63.2 from 0.61.4 buffer issue came back even with cheerio-without-node-native

Can someone summarize the problem? Is the problem that React Native doesn't support node.js modules that cheerio depends on? Modules like events & stream?

Can someone summarize the problem? Is the problem that React Native doesn't support node.js modules that cheerio depends on? Modules like events & stream?

yes

Okay, I've done a quick search through the source tree. Cheerio's source doesn't rely on any Node.js standard modules.

index.js
8:var staticMethods = require('./lib/static');
10:exports = module.exports = require('./lib/cheerio');
17:exports.version = require('./package.json').version;

test/xml.js
1:var expect = require('expect.js'),
2:    cheerio = require('..'),
4:      extend: require('lodash/assignIn'),

test/parse.js
1:var expect = require('expect.js'),
2:    assign = require('lodash/assign'),
3:    parse = require('../lib/parse'),
4:    defaultOpts = require('../lib/options').default;

lib/options.js
1:var assign = require('lodash/assign');

lib/utils.js
1:var cloneDeepWith = require('lodash/cloneDeepWith');

test/api/deprecated.js
6:var expect = require('expect.js'),
7:    fixtures = require('../fixtures'),
8:    cheerio = require('../..');

lib/static.js
1:var htmlparser2Adapter = require('parse5-htmlparser2-tree-adapter');
11:var serialize = require('dom-serializer').default;
12:var defaultOptions = require('./options').default;
13:var flattenOptions = require('./options').flatten;
14:var select = require('css-select');
15:var parse5 = require('parse5');
16:var parse = require('./parse');
18:  merge: require('lodash/merge'),
19:  defaults: require('lodash/defaults'),
38:  var Cheerio = require('./cheerio');

test/api/manipulation.js
1:var expect = require('expect.js'),
2:    cheerio = require('../..'),
3:    fruits = require('../fixtures').fruits,

test/api/utils.js
1:var expect = require('expect.js'),
2:    fixtures = require('../fixtures'),
3:    cheerio = require('../..');

test/api/css.js
1:var expect = require('expect.js');
2:var cheerio = require('../..');

test/api/forms.js
1:var expect = require('expect.js'),
2:    cheerio = require('../..'),
3:    forms = require('../fixtures').forms;

test/api/attributes.js
1:var expect = require('expect.js');
3:var cheerio = require('../..');
4:var fruits = require('../fixtures').fruits;
5:var vegetables = require('../fixtures').vegetables;
6:var food = require('../fixtures').food;
7:var chocolates = require('../fixtures').chocolates;
8:var inputs = require('../fixtures').inputs;

benchmark/suite.js
1:var fs = require('fs');
2:var path = require('path');
4:var Benchmark = require('benchmark');
5:var JSDOM = require('jsdom').JSDOM;
6:var Script = require('vm').Script;
7:var cheerio = require('..');

lib/parse.js
4:var htmlparser = require('htmlparser2');
5:var parse5 = require('parse5');
6:var htmlparser2Adapter = require('parse5-htmlparser2-tree-adapter');

benchmark/benchmark.js
3:var Suites = require('./suite');

lib/api/forms.js
14:      map: require('lodash/map'),

docs/template/publish.js
3:var doop = require('jsdoc/util/doop');
4:var env = require('jsdoc/env');
5:var fs = require('jsdoc/fs');
6:var helper = require('jsdoc/util/templateHelper');
7:var logger = require('jsdoc/util/logger');
8:var path = require('jsdoc/path');
9:var taffy = require('taffydb').taffy;
10:var template = require('jsdoc/template');
11:var util = require('util');
302:                        symbol.name = symbol.name.replace('module:', '(require("') + '"))';
525:        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
526:        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

lib/cheerio.js
6:var parse = require('./parse'),
7:    defaultOptions = require('./options').default,
8:    flattenOptions = require('./options').flatten,
9:    isHtml = require('./utils').isHtml,
11:      extend: require('lodash/assignIn'),
12:      bind: require('lodash/bind'),
13:      forEach: require('lodash/forEach'),
14:      defaults: require('lodash/defaults'),
21:  require('./api/attributes'),
22:  require('./api/traversing'),
23:  require('./api/manipulation'),
24:  require('./api/css'),
25:  require('./api/forms'),

lib/api/manipulation.js
10:var parse = require('../parse'),
11:    html = require('../static').html,
12:    text = require('../static').text,
15:    utils = require('../utils'),
21:      flatten: require('lodash/flatten'),
22:      bind: require('lodash/bind'),
23:      forEach: require('lodash/forEach'),

test/api/traversing.js
2:var expect = require('expect.js'),
3:    cheerio = require('../..'),
4:    food = require('../fixtures').food,
5:    fruits = require('../fixtures').fruits,
6:    drinks = require('../fixtures').drinks,
7:    text = require('../fixtures').text;

lib/api/traversing.js
10:var select = require('css-select'),
11:    utils = require('../utils'),
13:    uniqueSort = require('htmlparser2').DomUtils.uniqueSort,
16:      bind: require('lodash/bind'),
17:      forEach: require('lodash/forEach'),
18:      reject: require('lodash/reject'),
19:      filter: require('lodash/filter'),
20:      reduce: require('lodash/reduce'),

lib/api/attributes.js
10:var text = require('../static').text,
11:    utils = require('../utils'),
20:      forEach: require('lodash/forEach'),
21:      extend: require('lodash/assignIn'),
22:      some: require('lodash/some'),

lib/api/css.js
8:var domEach = require('../utils').domEach,
10:      pick: require('lodash/pick'),

test/cheerio.js
1:var expect = require('expect.js'),
2:    htmlparser2 = require('htmlparser2'),
3:    cheerio = require('../'),
4:    fixtures = require('./fixtures'),
8:      filter: require('lodash/filter'),

In principle, cheerio is just a text processor, so it doesn't really need to depend on events or stream.

In practice, we have some dependencies that are useful outside of cheerio. I'd suggest figuring out which dependencies are causing problems, then we can decide what to do about them.

@matthewmueller It was parse5's streaming related dependencies which were causing the issue for us. By removing the streaming-based parts of cheerio (see https://github.com/cheeriojs/cheerio/issues/1169#issuecomment-430909780) it functioned in RN fine for us.

react-native-cheerio working fine with react-native 0.63.2.

[email protected] should resolve this issue. Both parse5 and htmlparser2 had their native dependencies removed as far as I can tell; would love it if someone could have another try!

Closing this for now. Will reopen should someone report issues.

I just tested it and it seems to be working! thanks @fb55! 馃帀馃帀馃帀馃帀

Awesome, thanks for testing!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

miguelmota picture miguelmota  路  3Comments

tndev picture tndev  路  4Comments

chenweiyj picture chenweiyj  路  5Comments

misner picture misner  路  3Comments

trevorfrese picture trevorfrese  路  4Comments