JavaScript - Как заставить импорт ES6 работать в браузере?

Я начинаю новый проект, в котором я хотел бы иметь модули в стиле ES6, однако я не могу заставить его работать в браузере. Я использую Хром.

Я выделил проблему в несколько строк кода.

Вот мои 2 файла TypeScript:

app.ts

import { Component } from './component';

var component: Component = new Component();

component.ts

export class Component {

}

Вот как они компилируются в JavaScript:

app.js

import { Component } from './component';
var component = new Component();

component.js

export class Component {
}

Мой index.html содержит только тег скрипта. Я попробовал несколько вариантов, но ни один из них не сработал.

index.html #1

<script src="src/app.js" type="module"></script>

Скрипт не загружается. (Нет запроса на вкладке сети)

index.html #2

<script src="src/app.js" type=module></script>

Скрипт не загружается. (Нет запроса на вкладке сети)

index.html #3

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

Uncaught SyntaxError: неожиданный токен {

Я использую tsc для переноса TypeScript через код Visual Studio.

tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "typescript",
            "tsconfig": "tsconfig.json",
            "problemMatcher": [
                "$tsc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "reveal": "silent"
            }
        }
    ]
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es6",
    "sourceMap": false,
    "removeComments": false,
    "noImplicitReturns": true,
    "noImplicitAny": true,
    "preserveConstEnums": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "outDir": "../src/"
  },
  "exclude": [
    "logs",
    "node_modules"
  ]
}

person Royi Bernthal    schedule 27.10.2018    source источник
comment
Все просто: они не   -  person Victor    schedule 27.10.2018
comment
Уверены ли вы? Если да, то что я здесь неправильно понимаю? contentful.com/blog/2017/04/04/   -  person Royi Bernthal    schedule 27.10.2018
comment
Да, вы можете использовать модули напрямую в последних версиях браузеров, без упаковщика! Вы должны транспилировать файлы ts в js без определения какой-либо конкретной модульной системы. Затем вы можете загружать модули в браузере с помощью <script type=‘module’ src=‘thing.js’>   -  person Kokodoko    schedule 27.10.2018
comment
Хорошо, я делаю это сейчас, и js выглядит чище, но скрипт все еще не загружен. Я добавил дополнительную информацию внизу исходного вопроса.   -  person Royi Bernthal    schedule 27.10.2018
comment
Вы пытались написать минимальный конструктор? классы TS   -  person Luca Borrione    schedule 27.10.2018
comment
Я только что попробовал это, если это то, что вы имели в виду, те же результаты: export class Component {structor() {}}   -  person Royi Bernthal    schedule 27.10.2018
comment
В транспилированном app.js измените оператор import на следующее: import { Component } from './component.js'; Примечание: расширение файла .js было добавлено в спецификатор модуля. Синтаксис импорта ECMA-262 определяет только синтаксис модулей, а не конкретные механизмы их загрузки. Таким образом, требования для с или без суффикса .js могут различаться в зависимости от реализации. Однако включение расширения файла .js требуется в браузере Safari и, скорее всего, в Chrome. Кроме того, используйте <script src="src/app.js" type="module"></script> в index.html.   -  person RobC    schedule 29.10.2018
comment
Также стоит отметить, что Chrome также поддерживает расширение файла .mjs в спецификаторе модуля (как уже отмечалось здесь), однако расширение файла .mjs не работает с последней версией браузера Safari.   -  person RobC    schedule 29.10.2018
comment
Я тоже пробовал это. Это правда, в зависимости от вашей среды, но здесь это не имеет значения, поскольку запрос к сценарию даже не делается, это не похоже на то, что у меня есть запрос с неверным путем, который было бы легко отладить. Смотрите мой последний комментарий к ymz.   -  person Royi Bernthal    schedule 30.10.2018


Ответы (1)


Честно говоря, я думаю, что это хороший вопрос, потому что JS широко используется как в серверных, так и в клиентских приложениях, что способствует уже существующей путанице среди разработчиков.

Понятно, что ваш код TS написан как код на стороне сервера (вероятно, на Node.js). Попытка запустить его (как есть) на стороне клиента... ну... сложно. Причина: синтаксис, который вы используете в своем коде, предполагает работу на стороне сервера (а не на стороне клиента). Есть ли обходной путь? Ну да!

Хорошие новости:

JS ES6 имеет встроенный загрузчик модулей! (проверьте MDN)

Плохие:

  • Синтаксис отличается от синтаксиса Node.js загрузчика модулей (при экспорте модуля)
  • Поддержка очень частичная (только современные браузеры)

Некоторые дополнительные примечания:

  • Общий синтаксис загрузки модулей связан со сторонней библиотекой, которая называется require js (https://requirejs.org/ ). Вы можете использовать эту библиотеку в проектах на стороне клиента, но вы должны установить ее и правильно настроить (документы довольно ясно о том, как это сделать)
  • Вы всегда можете использовать средство запуска задач, например grunt (https://gruntjs.com/) или аналогичные проекты, которые помогут вам уменьшите и объедините весь ваш код в один файл в производстве. Почему ты спрашиваешь? Это явно поможет вам снизить нагрузку, когда клиент заходит на ваш сайт (чем меньше файлов, тем лучше с точки зрения сетевого трафика).

Как видите, на ваш вопрос нет быстрого или простого ответа... но это может быть хорошей отправной точкой для улучшения ваших знаний и создания лучших современных веб-приложений.

ОБНОВЛЕНИЕ

По запросу я создал небольшую демонстрацию в песочнице, которая показывает, как использовать нативный модуль ES6 (https://codesandbox.io/s/oj2rwm9v35)

index.html

<html>
<body>
    <div id="app"></div>
    <script type="module" src="src/primary.js"></script>
</body>
</html>

основной.js

import test from "./test";

test();

test.js

export default function test() {
  document.querySelector("#app").textContent = "Hello JS module!";
}
person ymz    schedule 27.10.2018
comment
Спасибо за ответ. Это все еще актуально для обновленного описания вопроса? - person Royi Bernthal; 27.10.2018
comment
Я полагаю, что да... ваши варианты: использовать собственные модули ES6 (и изменить способ экспорта своих функций), установить require (и настроить его правильно) или просто решить использовать средство запуска задач, которое поможет вам преобразовать TS в один минимизированный JS-файл, подходящий для клиентской среды. - person ymz; 27.10.2018
comment
Я пытаюсь использовать собственные модули ES6. Какая разница между тем, что я там делаю, и тем, как это должно быть? Следующий импорт: import { Component } from './component'; кажется, правильный синтаксис. Также меняется импорт {Component} из './component.js'; не имеет значения. Почему app.js даже не загружен? Я не мог понять из вашего ответа, было бы здорово, если бы вы могли уточнить этот момент. - person Royi Bernthal; 27.10.2018
comment
Спасибо за уточнение, так что я не думаю, что проблема в самом коде. Это работает для вас, когда вы открываете его в своей локальной файловой системе? Для меня это не так. И ваш код, и мой работают только при запуске на сервере. Есть идеи, почему? - person Royi Bernthal; 30.10.2018
comment
Ты прав. Он работает при запуске с локального хоста, а не из локальной файловой системы. Также обратите внимание, что я определил основной модуль (который ведет себя как модуль приложения) и попытался загрузить оттуда дополнительные модули — этот подход (определение вашего приложения как модуля, загрузка его из тега сценария и загрузка других модулей из этого модуля приложения) должен сделай трюк.. по моему мнению по крайней мере - person ymz; 31.10.2018