Make writing a habit together! This is the third day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

Understanding modularity

Commonjs

  • Loading modules:require
  • Export module:module.exports / exports.xxx

ES Module

  • Loading modules:import
  • Export module:export default / export xxx

Pain points analysis

Export a module utils using Commonjs

// test-cli-0174\bin\utils.js
module.exports = function () {
  console.log('hello utils');
};
Copy the code

Modules are introduced as ES Modules in the main file

// test-cli-0174\bin\index.js
#!/usr/bin/env node

import utils from './utils';

utils();
Copy the code

Cannot use import statement outside a module Cannot use import statement outside a module

So how do we get the Node environment to support ES Module?

Using webpack

Install webpack

npm i -D webpack webpack-cli
Copy the code

Modify the code

The main file uses require to call the webpack-built core.js

// test-cli-0174\bin\index.js
#!/usr/bin/env node
require('./dist/core');
Copy the code

Core.js uses es Module to introduce utils.js

// test-cli-0174\bin\core.js
import utils from './utils';
utils();
Copy the code

Configured webpack. Config. Js

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './bin/core.js'.output: {
    path: path.join(__dirname, '/dist'),
    filename: 'core.js',},mode: 'development'};Copy the code

Modify the scripts field of packag.json

  "scripts": {
    "build": "webpack"."dev": "webpack -w"
  },
Copy the code

Execute a build

npm run build
Copy the code

When the build is complete, the dist directory appears along with the built Core.js

Run the program again and find that it works.

You can start the listening state and automatically execute the build process when the file changes

npm run dev
Copy the code

Support for the Node built-in libraries via the Webpack Target property

When we call node’s built-in libraries, such as PATH or fs, the Webpack build will report an error because webpack is built using the Web environment by default. The Web environment does not have node’s built-in libraries, so we need to change the target property to Node.

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './bin/core.js'.output: {
    path: path.join(__dirname, '/dist'),
    filename: 'core.js',},target: 'node'.// The default is web
};
Copy the code
// test-cli-0174\bin\utils.js
import { pathExistsSync } from 'path-exists';

export function exists(p) {
  return pathExistsSync(p);
}
Copy the code
// test-cli-0174\bin\core.js
import path from 'path';
import { exists } from './utils';

console.log(path.resolve('. '));
console.log(exists(path.resolve('. ')));
Copy the code

Execute the program. There are no more problems.

Use Babel to support older versions of Nodes

Install dependencies

npm i -D 
babel-loader
@babel/core 
@babel/preset-env 
@babel/plugin-transform-runtime 
@babel/runtime-corejs3
Copy the code

Configuration webpack

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './bin/core.js'.output: {
    path: path.join(__dirname, '/dist'),
    filename: 'core.js',},mode: 'development'.target: 'node'.// The default is web
  module: {
    rules: [{test: /\.js$/,
        exclude: /(node_modules|dist)/,
        use: {
          loader: 'babel-loader'.options: {
            presets: ['@babel/preset-env'].plugins: [['@babel/plugin-transform-runtime',
                {
                  corejs: 3.regenerator: true.useESModules: true.helpers: true,},],],},},},],},};Copy the code

How does Node natively support ES Module

You need to change the filename suffix to.mjs, and once you use MJS, all content must use ES Module, do not mix, otherwise an error will be reported.

// test-cli-0174\bin\index.mjs
#!/usr/bin/env node

import './core.mjs';
Copy the code
// test-cli-0174\bin\core.mjs
import path from 'path';
import { exists } from './utils.mjs';

console.log(path.resolve('. '));
console.log(exists(path.resolve('. ')));
Copy the code
// test-cli-0174\bin\utils.js
import { pathExistsSync } from 'path-exists';

export function exists(p) {
  return pathExistsSync(p);
}
Copy the code

Finally, the program is executed by an instruction

node --experimental-modules bin/index.mjs
// After node14, you don't need --experimental-modules
node bin/index.mjs
Copy the code

You get the same result, no problem.

If you don’t want to change the suffix to.mjs, you can specify the type field as module in your project’s package.json file.

{
   "type": "module"
}
Copy the code

Once set, JS scripts in this directory are interpreted as ES6 modules.