{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/run-jsx-from-command-line/","result":{"data":{"markdownRemark":{"html":"<p>Here’s a simplified root <code>.jsx</code> file I’d like to run to generate some HTML from the command-line.</p>\n<p>index.jsx:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk3\">// Use import statements:</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk4\">*</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> </span><span class=\"mtk12\">React</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;react&quot;</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">renderToStaticMarkup</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;react-dom/server&quot;</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk3\">// Use JSX</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">The app</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk3\">// Use an API only available in node (and some more JSX):</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">stdout</span><span class=\"mtk1\">.</span><span class=\"mtk11\">write</span><span class=\"mtk1\">(</span><span class=\"mtk11\">renderToStaticMarkup</span><span class=\"mtk1\">(</span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">App</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">));</span></span></span></code></pre>\n<p>I’ll use <code>yarn</code> to install those imported libs, which has the side-effect of creating a <code>package.json</code> file:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"bash\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">yarn add react react-dom</span></span></span></code></pre>\n<p>I want to run <code>index.jsx</code> directly, without having to transpile then execute as two separate steps. The script doesn’t look particularly special, but does use <code>import</code> and JSX, two features that cause problems as I’m not using a bundler.</p>\n<p>Executing <code>node index.jsx</code> gives this error (caused by the <code>import</code> statements):</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\">(node:58928) Warning: To load an ES module, set &quot;type&quot;: &quot;module&quot; in the package.json or use the .mjs extension.</span></span></code></pre>\n<p>I try creating a <code>package.json</code> and setting <code>\"type\": \"module\"</code>, and re-run <code>node index.jsx</code> to get a different error (caused by file extension):</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\">TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension &quot;.jsx&quot; for /...</span></span></code></pre>\n<p>Renaming <code>index.jsx</code> to <code>index.js</code> and executing with <code>node index.js</code> gives a different error:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\">const App = () =&gt; &lt;div&gt;The app&lt;/div&gt;;</span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\">                  ^</span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\">SyntaxError: Unexpected token &#39;&lt;&#39;</span></span></code></pre>\n<p>(I get the same error if I try changing the file extension to <code>.mjs</code> and running <code>node index.mjs</code>)</p>\n<p>At this point it feels like I’ve hit a brick wall with <code>node</code>, so need to look at alternative solutions.</p>\n<p>Before going any further I need to revert my changes: restoring the original filename of <code>index.jsx</code>, and removing the <code>\"type\": \"module\"</code> property from <code>package.json</code>.</p>\n<h2>Setup babel-node</h2>\n<p>I want to transpile-and-run in one step, which is exactly what <a href=\"https://babeljs.io/docs/en/babel-node\"><code>babel-node</code></a> is designed for.</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"bash\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk3\"># Install all libs needed to run babel-node on a file containing JSX:</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">yarn add -D @babel/core @babel/node @babel/preset-env @babel/preset-react</span></span></span></code></pre>\n<p>Create a <code>babel.config.json</code> file:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"json\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">{</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;presets&quot;</span><span class=\"mtk1\">: [</span><span class=\"mtk8\">&quot;@babel/preset-env&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;@babel/preset-react&quot;</span><span class=\"mtk1\">]</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<p>Use <code>npx babel-node index.jsx</code> to run, and we can see the output:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">The app</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>That’s it; it’s working! We can now iterate and experiment to our heart’s content.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    position: relative;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n    line-height: 1.4;\n  }\n  \n  .grvsc-code {\n    display: table;\n  }\n  \n  .grvsc-line {\n    display: table-row;\n    box-sizing: border-box;\n    width: 100%;\n    position: relative;\n  }\n  \n  .grvsc-line > * {\n    position: relative;\n  }\n  \n  .grvsc-gutter-pad {\n    display: table-cell;\n    padding-left: 0.75rem;\n    padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2);\n  }\n  \n  .grvsc-gutter {\n    display: table-cell;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n  }\n  \n  .grvsc-gutter::before {\n    content: attr(data-content);\n  }\n  \n  .grvsc-source {\n    display: table-cell;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-source:empty::after {\n    content: ' ';\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n  }\n  \n  .grvsc-gutter + .grvsc-source {\n    padding-left: 0.75rem;\n    padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2);\n  }\n  \n  /* Line transformer styles */\n  \n  .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before {\n    content: ' ';\n    position: absolute;\n    width: 100%;\n  }\n  \n  .grvsc-line-diff-add::before {\n    background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2));\n  }\n  \n  .grvsc-line-diff-del::before {\n    background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2));\n  }\n  \n  .grvsc-line-number {\n    padding: 0 2px;\n    text-align: right;\n    opacity: 0.7;\n  }\n  \n  .default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .default-dark .mtk3 { color: #6A9955; }\n  .default-dark .mtk15 { color: #C586C0; }\n  .default-dark .mtk1 { color: #D4D4D4; }\n  .default-dark .mtk4 { color: #569CD6; }\n  .default-dark .mtk12 { color: #9CDCFE; }\n  .default-dark .mtk8 { color: #CE9178; }\n  .default-dark .mtk11 { color: #DCDCAA; }\n  .default-dark .mtk17 { color: #808080; }\n  .default-dark .mtk10 { color: #4EC9B0; }\n  .default-dark .grvsc-line-highlighted::before {\n    background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1));\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5));\n  }\n</style>","timeToRead":2,"frontmatter":{"title":"Running .jsx from the command-line","blurb":"A few setup steps to help write and run .jsx from the command-line","date":"2020-11-30T10:28:48.004Z","modified":null}}},"pageContext":{"slug":"/blog/run-jsx-from-command-line/","next":{"fields":{"slug":"/blog/run-tsx-from-command-line/"},"frontmatter":{"title":"Running .tsx from the command-line"}},"previous":{"fields":{"slug":"/blog/motd/"},"frontmatter":{"title":"Motivational MOTD"}}}},"staticQueryHashes":["1192980692"]}