2

I never really thought about it until I switched from webpack to brunch where I saw the following lines in index.html:

<script type="text/javascript">
      require('main');
    </script>

When you try to simply open up a local html page (even after everything's been built in webpack), it produces errors (SCRIPT5009: SCRIPT5009: 'require' is not defined) and doesn't render correctly, but when you open the page through a dev server it renders correctly.

Why are dev servers required for bundlers? What are the dev servers doing behind the scenes to allow the browser to properly render pages with bundles? Isn't the rendering capability built into the browser itself?

Originally I thought it was putting up a node server to help translate commands such as require(), but the above shows that the line was passed through to the browser. Why does the browser choke on that command when you just open the html file versus when it's delivered via a server?

On a side note everything works fine when the page is delivered via apache as well. If it is some sort of node translation, then how does apache not choke on it?

edit:

The files that show delivered are:

logo.png (just a vue logo) app.js (the bundled javascript file) the html file, which looks like:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vue-webpack-brunch</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="/app.js"></script>
    <script type="text/javascript">
      require('main');
    </script>
  </body>
</html>

Everything is delivered exactly like that, and that's the extent of the project. If the javascript bundle were including requirejs then it should also work if you just open the file locally as well

Edit 2:

typing require in the console produces the following:

(t,r){null==r&&(r="/");var i=l(t);if(o.call(n,i))return n[i].exports;if(o.call(e,i))return u(i,e[i]);throw new Error("Cannot find module '"+t+"' from '"+r+"'")}: 
David Torrey
  • 1,335
  • 3
  • 20
  • 43
  • 1
    "it produces errors" — Reading the errors would probably provide a clue! – Quentin Jul 08 '18 at 07:56
  • Probably a duplicate of https://stackoverflow.com/questions/10752055/cross-origin-requests-are-only-supported-for-http-error-when-loading-a-local – Quentin Jul 08 '18 at 07:57
  • it's not the same, you clearly didn't read my question. I'm trying to understand what the web server does that simply opening a file doesn't. the error above just says that require is not defined, it doesn't explain what the web server does to make it defined or fix it – David Torrey Jul 08 '18 at 08:00
  • 1
    "you clearly didn't read my question" — You clearly didn't read the possibly duplicate clearly. Try again and see how the solution to the problem is "use a webserver". You also failed to provide a [mcve], which is why I commented with vague speculation instead of closing the question or answering it. – Quentin Jul 08 '18 at 08:09
  • you clearly didn't read my question because I already understand you need a web server, i'm trying to understand why. it's not vague, you require web servers for bundles and I'm trying to understand why. the link you provided just says "use web servers" that doesn't answer my question – David Torrey Jul 08 '18 at 08:12
  • Provide a [mcve] – Quentin Jul 08 '18 at 08:12
  • ok, build a webpack bundle, import it into an html file and try to load it directly instead of through a server, then try to load it through apache. that's not repeatable? that's not verifiable? I provided all the information needed to show that it would produce an issue – David Torrey Jul 08 '18 at 08:14
  • Though the `require()` statement hasn't been modified, might the dev server have injected another script that may provide/define `require()`? Take a look in the Network and/or Elements panel with the dev tools (F12). – try-catch-finally Jul 08 '18 at 08:16
  • @DavidTorrey — Stackoverflow expects you to provide a [mcve] and not ask everyone trying to help to write their own project from scratch before they can help. – Quentin Jul 08 '18 at 08:17
  • @try-catch-finally – The OP said that it worked on plain apache as well as the dev server. – Quentin Jul 08 '18 at 08:18
  • @try-catch-finally the network panel shows only 3 files delivered. i will edit the question to include them – David Torrey Jul 08 '18 at 08:19
  • edited to add more info – David Torrey Jul 08 '18 at 08:22
  • @Quentin I see your point, thank you – David Torrey Jul 08 '18 at 08:30

2 Answers2

2
<script src="/app.js"></script>

You are loading /app.js which will define your require function.

The URL starts with a /.

If you load it from a webserver, the / refers to the root of the site.

If you load it from your local file system, then the / refers to the root of your filesystem (or disk if you are Windows). This will be the wrong place because webpack will not generate it there (you would not want c:\app.js created for every application you built with webpack).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I think that is valid, I removed the / and made it a relative reference but it just says "syntax error" – David Torrey Jul 08 '18 at 08:27
  • oops, i had made a typo in there as well. ok, so the bundle IS including require, it's just a matter of the pathing. thank you, I was certain there couldn't be anything additional happening which is why I was so confused – David Torrey Jul 08 '18 at 08:27
0

The require keyword is giving errors because it's a made up way to require external files. If you used import, the standard native implementation, it would work out of the box on newer browsers. Bundlers aren't required.

Require came from https://requirejs.org/

They're looking for that word require and, essentially, injecting code at that source path into a built file. It'd be like if I made a injectFile keyword for my InjectFileJS project.

<script type="text/javascript">
  injectFile('main');
</script>

That would produce the same error, injectFile is undefined. You would need to run my made up file loader on your web server to parse and transpile the files for that function to exist.

However, if you use import you can get away with not having a bundler as a requirement on new browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Oscar Godson
  • 31,662
  • 41
  • 121
  • 201
  • 1
    Why down vote? This literally answers the exact question? – Oscar Godson Jul 08 '18 at 08:08
  • The question is "Why does using a webserver solve the problem?". This doesn't answer that, it just explains why `require` is undefined unless "something" is done. It doesn't explain why using a web server will make `require` defined. – Quentin Jul 08 '18 at 08:10
  • i didn't downvote, so web servers such as apache natively have requirejs included? because it works without adding requirejs when delivered from a web server such as apache – David Torrey Jul 08 '18 at 08:12
  • @DavidTorrey — "so web servers such as apache natively have requirejs included" — No, they don't. – Quentin Jul 08 '18 at 08:13
  • @Quentin added a bit more detail to mention transpiling on a web server – Oscar Godson Jul 08 '18 at 08:13
  • @OscarGodson — The OP said that using Apache solves the problem and that the `require` statement is delivered to the browser. There's no transpiling going on. – Quentin Jul 08 '18 at 08:14
  • @DavidTorrey `require` doesn't exist in ECMAScript so that can't be true or you have some Apache plugin installed or something to do it (I dont know of any but I guess it's possible). If by Apache you mean running Node, then yes, Node has it's own `require` keyword that does this but it will not work in the context of a browser. – Oscar Godson Jul 08 '18 at 08:15
  • checking to see what modules are included – David Torrey Jul 08 '18 at 08:16
  • @DavidTorrey Have you actually verified what code reaches the browser or just checking the source code in your text editor? – Álvaro González Jul 08 '18 at 08:17
  • i'm checking via f12 in the browser – David Torrey Jul 08 '18 at 08:18
  • @DavidTorrey At the location you said it's working can you just type `require` and hit enter in the browser and paste the results? – Oscar Godson Jul 08 '18 at 08:19