typescript - შემიძლია გავიტანო წაკითხვადი შედეგი webpack-იდან?


მინდა ჩემი Typescript კოდი გავყო მოდულებად გაუმჯობესების მიზნით და დავაკავშირო ისინი ერთ ერთიან კომპილირებულ JavaScript ფაილში ბრაუზერისთვის. Webpack ჟღერს სწორედ ისე, როგორც მე მსურს, რადგან ის გადაიყვანს ჩემს Typescript-ს, გააერთიანებს მოდულებს და მარტივად შემიძლია მქონდეს განსხვავებული build ამინანიცის განვითარების და წარმოებისათვის, აირჩიო, ჩავთვალო თუ არა minify, cache-bust, ფაილების ცვლილების ძებნა და ა.შ. ასევე მინდა ზოგი ჩემი მოდული ცალ-ცალკე დამაკავშირო, დინამიურად ჩატვირთვისათვის, რაც რთული გამოსაყენებელი არაა. და შეუძლია ჩემი CSS-ის დამუშავება, მათ შორის Sass-დან კომპილაცია. ერთი ხელსაწყო ამას ყველაფერს გააკეთებს? სად უნდა დავრეგისტრირდე?

მაგრამ ცოტა იმედგაცრუებული ვიყავი, როცა ვნახე JavaScript, რომელიც webpack-მა შექმნა. შემიძლია გავუძლო მასში ზედა ნაწილში დამატებულ boilerplate-ს, მიუხედავად იმისა, რომ მასზე ცოტა მეტად ველოდი. და მინიფიცირებული ვერსია პრაქტიკულად შეუძლებელია აღადგინო რაიმე გასაგებად, მაგრამ ეს შეიძლება თვისებად ჩაითვალოს, არა?

რაც ჭირს ჩემთვის არის ის, რომ განვითარების ტრიბუტი პრაქტიკულად უცნობად გამოიყურება წყაროდან, და კოდი იტვირთება უზარმაზარი, უშნო eval სტრიქონით. და თითქოს არ ესმით ჩემი ექსპორტები window ობიექტში, ასე რომ, მე ვერ მივიღებ არაფერს ბრაუზერის კონსოლიდან. ამიტომ გენერირებული კოდი არა მხოლოდ საკმაოდ გამჭვირვალეა, არამედ მისი შეცდომების მოძიება ბევრად რთულია (თუნდაც სათავო რუკების გამოყენებით).

არსებობს რაიმე გზა, რომ მე დავაყენო ისე, რომ ეს დამინი გამომცეს ისეთი debug გამოსავალი, რომელიც უფრო ადვილად წასაკითხი და გასაწყვეტი იქნება?

აქ არის ჩემი მარტივი კონფიგურაცია ტესტირებისთვის:

// ./webpack.config.js

const path = require("path");

module.exports = {
    entry: "./ts/main.ts",
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "./js")
    },
    module: {
        rules: [
            {
                use: "ts-loader",
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        extensions: [".ts", ".tsx"]
    }
};
// ./tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "amd",
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "esModuleInterop": true
    }
}

დემონსტრაციისთვის, მე მაქვს ძალიან უბრალო სატესტო ფაილი:

// ./ts/main.ts

export function hello(){return "Hello, World!";}

console.log(hello());

მაინც არ მინდა აქ მთლიანად შედეგის ჩასმა, რადგან ეს ბევრია იმისთვის, რომ ვინმემ დახედოს, ამიტომ აქ არის JS Bin-ზე. მაგრამ მოკლედ დასაჯამებლად, ის მსგავსია:

// ./js/main.js

/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};
/******/
/******/    // The require function
/******/    function __webpack_require__(moduleId) {
// ....... snip 76 lines ....... 
/******/    // Load entry module and return exports
/******/    return __webpack_require__(__webpack_require__.s = "./ts/main.ts");
/******/ })
/************************************************************************/
/******/ ({

/***/ "./ts/main.ts":
/*!********************!*\
  !*** ./ts/main.ts ***!
  \********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__
// ....... snip 223 characters .......
function hello() { return \"Hello, World!\"; }\n    exports.hello = hello;\n    console.log(hello());\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
// ....... Hey, there's my code! .......
// ....... snip 133 more characters
// //# sourceMappingURL=data:application/json;charset=utf-8;base64
// ....... snip the source map data (gobbledygook that's actually useful)
");

/***/ })

/******/ });

ახლა, თუ ამას HTML ფაილში ჩავამატებ და ბრაუზერში დავტვირთავ ...

<html>
    <head>
        <script src="js/main.js"></script>
    </head>
</html>

ვხედავ ჩემს კონსოლის ლოგს, მაგრამ ვერ ვწვდი ჩემს ფუნქციას.

პასუხი #1

ვებპაკის მიერ წარმოქმნილი პაკეტი არ არის განკუთვნილი ადამიანებისთვის დასაპარათებლად, ყველაზე ცოტა პირდაპირ. ეს სიმართლეა ასევე განვითარებისა პერიოდში.

Webpack-ს აქვს devtool პარამეტრი, რომელიც უთითებს მას გამომავალი წყაროს რუკების შექმნაზე. ეს საშუალებას გაძლევთ დააკვირდეთ კოდს, რომელიც გამოიყურება როგორც თქვენი ორიგინალური წყარო ბრაუზერის დებაგერში, მიუხედავად იმისა, რომ ბრაუზერი სხვადასხვა კოდს ასრულებს.

Webpack-ით შექმნილი კოდი უნდა განსხვავდებოდეს ორიგინალიდან. შეგიძლიათ დაწეროთ import './foo', მაგრამ foo.js თავისთავად ცალკე ფაილი შენახულში არაა, ეს უბრალოდ კოდის ნაწილი არის ამ შენახულში. ამიტომ webpack გადაამუშავებს იმ import-ს, რათა ის სხვაგვარად იმუშაოს.

და TypeScript მუშაობს მსგავსად. ის მხარს უჭერს ფუნქციებს, რომლებსაც ყველა ბრაუზერი შესაძლოა ვერ მხარს უჭერდეს, და TypeScript-ის კომპილატორი თარგმნის ამ ტექნოლოგიებს რაღაც ისეთი, რასთანაც უმეტესობა ბრაუზერის შეძლებს მუშაობას, ზოგჯერ ძალიან დეტალურად.


ბოლოს, ეს განსხვავებული საკითხია:

და ჩანს, რომ ჩემს ექსპორტს არ უმატებს window ობიექტს

ეს არის ინტენციურად.

რაღაცის ექსპორტირება ფაილიდან არასოდეს დაამატებს მას გლობალურ სფერზე. ეს ინარჩუნებს გლობალურ სფერს სუფთა. თუ გსურთ რაიმე გლობალურ სფერზე, თქვენ დაგჭირდებათ მისი იქამდე სპეციალურად განთავსება:

window.foo = { abc: 123 }

მაგრამ ჩვეულებრივ, აქ იგულისხმება, რომ თქვენი პაკეტის სხვა მოდულებმა შეიძლება იმპორტირდნენ მოდულები და გამოიყენონ მათი კოდი ისე, რომ არაფერმა არ არსებობდეს გლობალურ სივრცეში.

import foo from './foo'

console.log(foo.abc)

ახლა, თუ შენ გაქვს კოდი შენს პაკეტის გარეთ, რომელიც დამოკიდებულია კოდზე შენს პაკეტში, ეს აშკარად რთულდება, და შენ დაგჭირდება მთლიანი სადგომისთვის მნიშვნელობების დასაბარებლად. მაგრამ უფრო ხშირად, უბრალოდ იმპორტირებ საჭირო მოდულს მოდულიდან, რომელიც ასევე იმავე პაკეტში იქნება, და შენ შენარჩუნებ მთლიანი სადგომის სრულ ცენტრალიზებულობას.