Как импорт javascript находит модуль без расширения? - PullRequest
3 голосов
/ 20 марта 2019

Я понимаю, что мы можем использовать import {x} from "./file", и переменная x будет импортирована из файла file.js в том же каталоге.Как это обрабатывается, если в каталоге есть файлы с одинаковыми именами с разными расширениями?

Например, если бы в одном каталоге были файлы file.js и file.ts, как бы себя вел import {x} from "./file"?Зависит ли это от версии javascript?

Ответы [ 2 ]

4 голосов
/ 22 марта 2019

Зависит ли это от версии javascript?

Нет, это зависит от поведения среды выполнения javascript, то есть от того, что выполняет ваш сценарий.

В node.js с включенными модулями ES существует заранее определенный список расширений файлов, в которых производится поиск, если URL в import не имеет расширения. Распознаются следующие расширения: ". Mjs", ".js", ".json", ".node" . Кроме того, если путь относится к каталогу, выполняется поиск в файле «index», также с различными расширениями.

В node.js без включенных модулей ES в сценарии не может быть import, когда он выполняется - сначала нужно перенести его в формат CommonJS, а затем сценарий должен использовать require, который распознает аналогичный список расширений, но без "mjs".

В браузере, если он имеет встроенную поддержку модулей ES, браузер не будет добавлять какие-либо расширения к URL-адресу, который вы указали в import - если ваш файл, например, имеет расширение .js, вы должны написать import {x} from "./file.js". У браузеров нет полезного способа узнать, какие файлы с какими расширениями доступны на сервере.

В браузерах без встроенной поддержки модулей ES вам снова придется переносить любой сценарий, содержащий операторы import, а затем использовать какой-либо пакет или загрузчик модулей для запуска скомпилированных сценариев в браузере.

Например, если бы в одном каталоге были файлы file.js и file.ts, как бы себя вел импорт {x} из "./file"?

Это зависит.

Когда вы переносите или компилируете свой скрипт, то, какие расширения распознаются, зависит от компилятора и настроек, которые вы предоставляете для компиляции.

Например, в веб-пакете есть предопределенный список поддерживаемых расширений - '. Wasm', '.mjs', '.js', '.json' , но его можно изменить с помощью resol.extension в вашем файле webpack.config.js.

Если вы используете webpack с плагином ts-loader , расширение .ts также распознается, но загрузчик попытается сделать так, чтобы файл .ts был скомпилирован в .js файл и попытается использовать этот скомпилированный файл .js при связывании.

Если вы используете простой компилятор сценариев для компиляции ваших сценариев, компилятор будет искать файл с расширением «.ts» для проверки типов, но он сгенерирует код, который будет искать файл с расширением «.js», когда Вы запустите сценарий. Кроме того, если файл с расширением «.ts» скомпилирован, компилятор запишет сгенерированный код в файл с расширением «.js» и может перезаписать ваш файл javascript, если он у вас есть, в зависимости от настройки, указывающей, куда выводить Файлы .js.

0 голосов
/ 09 июля 2019

Я столкнулся с той же проблемой, и я "легко" решил, так: URL REWRITING, что я имею в виду?я собираюсь объяснить это с самого начала!

Вот история из скомпилированного кода Typescript, я хотел получить некоторый код ES6 (цель es2015 в tsconfig.json), чтобы сохранить в конечном кодеоригинальный синтаксис: импорт / экспорт, который я написал в Typescript (действительно, в конце концов, я не хотел использовать загрузчики модулей для ES5 !! Потому что это старая школа ...).

Дело в том, что, когда Typescript генерирует ES6, он полностью сохраняет неизменными синтаксисы: import .. from "./.../MyJSFile", поэтому он сохраняет его без расширения" .js "!!И, конечно же, в коде Typescript вы не можете упомянуть расширение в синтаксисе импорта!(предполагается, что это «.ts»).

Итак, теперь у меня есть, как и у вас, сгенерированный код ES6, содержащий синтаксисы импорта, которые НЕ упоминают расширение «.js»импортированные файлы.Так в чем же проблема?

Проблема в следующем:

  • Чтобы выполнить такой код в браузере, потому что он использует модули ES6, которые вы ДОЛЖНЫ запустить изВЕБ-СЕРВЕР (не важно какой)!

  • НО!ни один веб-сервер не найдет файлы, которые вы хотите импортировать ( import ... from "./.../MyJSFile"), потому что, как говорится, без расширения этот ресурс не существует!и на самом деле это не так !!НО мы знаем, что ресурс "./.../ MyJSFile.JS" СУЩЕСТВУЕТ!Так ??Вы видите, что я иду?

    ВЫ ТОЛЬКО ДОЛЖНЫ НАПИСАТЬ: ПРАВИЛА ПЕРЕДАЧИ URL ДЛЯ ВЕБ-СЕРВЕРА , и вот что я сделал, чтобы решить!Я сделал это с:

    • веб-сервером APACHE (который имеет директиву: AllowOverride All, чтобы разрешить перезапись URL-адреса !!).
    • , а затем ятолько что создал файл .htaccess в корне моего сайта localhost, в котором я говорю ему: если запрошенный ресурс не существует, попробуйте найти (путем перезаписи URL) то же имя ресурса, НО, с ".js"расширение в конце этого!И это работает прекрасно!Вот мой .htaccess в его простейшей рабочей форме:

      RewriteEngine on
      
      RewriteCond %{REQUEST_FILENAME} !-f
      
      RewriteRule  ^(.*)(/[A-Za-z0-9_]+)$  $1$2.js   [L]
      

И это действительно все, что вам нужно сделать!с сервером Apache.Так что имейте в виду, что бы ни был веб-сервер, идея такова: перезапись URL-адреса!

Я также использовал тот же принцип с веб-сервером NODE.JS, который я создал, вот его полный протестированный код,это работает абсолютно нормально (nodeJsAsWebServer.js):

//In terminal, just run : node nodeJsAsWebServer  
//to launch this below Web Server. (CTRL+C to stop) .
//
//And then in the browser, just invoke your ES6 code 
//(via normal html call), 
//on this domain : localhost:555

//------- nodeJsAsWebServer.js ---------

const oHttpTool = require('http');
const oFilesTool = require('fs');
const oPathesTool = require('path');

const oMIMETypes = {
  'html': 'text/html',
  'css': 'text/css',
  'js': 'text/javascript',

 'json': 'application/json',

  'png': 'image/png',
  'jpg': 'image/jpeg',
  'ico': 'image/x-icon',

  'wav': 'audio/wav',
  'mp3': 'audio/mpeg',

  'pdf': 'application/pdf',
  'doc': 'application/msword'
};

let oMyWebServer = oHttpTool.createServer(function (req, res) {

  console.log("\n\n=========================================================");
  console.log("=========================================================\n");

  let sSubUrl = req.url;
  console.log("Client code asks for: "+sSubUrl);

  let sFileExtension = oPathesTool.parse(sSubUrl).ext.substr(1);    
  let sMIMEType = oMIMETypes[sFileExtension];
  console.log("Asked MIMEType="+sMIMEType);

  let sFileHDDPath = __dirname; //Real path on server hard disk
  let sFileToRead = sFileHDDPath+sSubUrl;
  console.log("FileToRead="+sFileToRead);
  oFilesTool.exists(sFileToRead, function (pbFileExists) {
    if(!pbFileExists) {
      console.log(`  - File NOT FOUND on the server!  -`);
      if (sFileExtension==="") { //If the requested URL doesn't have any extension !
        let sNewUrl = sSubUrl+".js"; //<<<<<<<<<<<< URL Rewriting
        console.log(" REDIRECTION ...(sNewUrl='"+sNewUrl+"'; ldUrl='"+sSubUrl+"')");
        res.writeHead(301, {Location:sNewUrl});//Redirect, we try to load this newURL
        res.end();

      } else { //if the URL already had an extension.
        res.statusCode = 404;
        res.end();
      }

    } else { //Normal case, when the requested resource exists.
      oFilesTool.readFile(sFileToRead, function(poError, poData){
        if(poError){
          res.statusCode = 500;
          console.log("ERROR getting file content !!", poError);
          res.end();

        } else { //We send the file whole content and with a header.
          res.setHeader('Content-type', sMIMEType );
          res.end(poData); //<<Also works for Binary files such as Image, PDF, etc..
        }
      });      
    }
  });

});


let iPort=555; //<<< choose your port on localhost.
console.clear();
console.log("Node Web Server listening on localhost:"+iPort+" ...    (CTRL+C to stop)");
oMyWebServer.listen(iPort);
...