DEV Community

loading...

[Client][TypeScript] Try import|export without Webpack

Masui Masanori
Programmer, husband, father I love C#, TypeScript, etc.
・4 min read

Intro

From ES6, I can import|export JavaScript files as modules on client-side.
But I have used Webpack to bundle files and never tried it.

Because I want to know should I keep using Webpack or importing|exporting modules, I will try it.

Environments

  • Node.js ver.16.6.0
  • TypeScript ver.4.3.5
  • Webpack ver.5.42.0

import|export modules

I can import and export modules as same as using Webpack.

module.page.ts

import * as second from './secondModule';

export function init(): void {
    second.addMessage();
}
Enter fullscreen mode Exit fullscreen mode

secondModule.ts

function addMessage(): void {
    const target = document.getElementById('message_target') as HTMLElement;
    target.textContent = 'Hello World';
}
export { addMessage }
Enter fullscreen mode Exit fullscreen mode

But there are some differences.
For example, this samples only can work on web server.
If I open the HTML file as local files, I will get errors because of CORS restrictions.

I have to add "type="module"" in script tags and when I call exported functions from HTML, I must import the module file.

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>module sample</title>
        <meta charset="utf-8">
    </head>
    <body>
        <div id="message_target"></div>
        <script type="module">
            import { init } from './js/module.page.js';
            init();
        </script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

File not found

In this sample, I got one more exception because "secondModule.js" wasn't found.

I used Express and publish JavaScript files as static files.

[Server] index.ts

...
// To receive JSON value from client-side
app.use(express.json());
// To receive Blob value from client-side
app.use(express.raw());
app.use(express.static('clients/public'));
...
Enter fullscreen mode Exit fullscreen mode

I tried importing the file like "import * as second from './secondModule';".

The file path would look like "localhost:3000/js/secondModule", but I really needed to set the path to "localhost:3000/js/secondModule.js".

So I can import the secondModule.js like below.

module.page.ts

import * as second from './secondModule.js';

export function init(): void {
    second.addMessage();
}
Enter fullscreen mode Exit fullscreen mode

If I do that, I should research how to add file extensions automatically when I import module files.

Using libraries

How about any libraries like "Moment.js"?

Of cource, it won't be compiled and copied into the output directory.
So I have to copy the files by myself.

Shall I import|export in ES6 way or keep using Webpack?

At least in these samples, I prefer to use Webpack or any other bundling tools.
Because I felt they are more simpler and they can be used in a wider range of environments include IE.

But I'm also interested in import|export of ES6.

Dynamic import

From ES2020, I can also import modules dynamically.
I don't need adding "type="module"" into the script tag.

module.page.ts

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function init(): void {
    import('./secondModule.js').then(v => v.addMessage());  
}
Enter fullscreen mode Exit fullscreen mode

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>module sample</title>
        <meta charset="utf-8">
        </head>
    <body>
        <div id="message_target"></div>
        <script src="./js/module.page.js"></script>
        <script>init();</script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Dynamic import with Webpack

I can also use dynamic import in the project what is bundled by Webpack.

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>module sample</title>
        <meta charset="utf-8">
        </head>
    <body>
        <div id="message_target"></div>
        <script src="./js/module.page.js"></script>
        <script>Page.init();</script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

module.page.ts

export function init(): void {
    import('./secondModule').then(v => v.addMessage());  
}
Enter fullscreen mode Exit fullscreen mode

After compiling, "secondModule.js" is separated from the bundled file.

ts_secondModule_ts.js

/*
 * ATTENTION: An "eval-source-map" devtool has been used.
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
(self["webpackChunkPage"] = self["webpackChunkPage"] || []).push([["ts_secondModule_ts"],{

/***/ "./ts/secondModule.ts":
/*!****************************!*\
  !*** ./ts/secondModule.ts ***!
  \****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"addMessage\": () => (/* binding */ addMessage)\n/* harmony export */ });\nfunction addMessage() {\r\n    const target = document.getElementById('message_target');\r\n    target.textContent = 'Hello World';\r\n}\r\n\r\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9QYWdlLy4vdHMvc2Vjb25kTW9kdWxlLnRzPzNkZjQiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ3NCIiwiZmlsZSI6Ii4vdHMvc2Vjb25kTW9kdWxlLnRzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gYWRkTWVzc2FnZSgpIHtcclxuICAgIGNvbnN0IHRhcmdldCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtZXNzYWdlX3RhcmdldCcpO1xyXG4gICAgdGFyZ2V0LnRleHRDb250ZW50ID0gJ0hlbGxvIFdvcmxkJztcclxufVxyXG5leHBvcnQgeyBhZGRNZXNzYWdlIH07XHJcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./ts/secondModule.ts\n");

/***/ })

}]);
Enter fullscreen mode Exit fullscreen mode

Lazy loading is very useful in some situations.
So I would use it when lazy loading is needed and IE compatibility is not needed :P

Resources

Discussion (0)