วิธีการป้องกัน moment.js จากการโหลดสถานที่ด้วย webpack?


199

มีวิธีใดที่คุณสามารถหยุดไม่ให้moment.jsโหลดโลแคลทั้งหมด (ฉันต้องการภาษาอังกฤษ) เมื่อคุณใช้เว็บแพค? ฉันกำลังดูแหล่งที่มาและดูเหมือนว่าหากhasModuleมีการกำหนดไว้ซึ่งเป็นของ webpack ก็จะพยายามrequire()ทุกสถานที่ ฉันค่อนข้างมั่นใจว่าต้องมีคำขอดึงเพื่อแก้ไข แต่มีวิธีใดบ้างที่เราสามารถแก้ไขได้ด้วยการกำหนดค่า webpack

นี่คือ webpack config ของฉันที่จะโหลดโมเมนต์ js:

resolve: {
            alias: {
                moment: path.join(__dirname, "src/lib/bower/moment/moment.js")
            },
        },

require('moment')จากนั้นทุกที่ฉันต้องการมันผมก็ทำ ใช้งานได้ แต่กำลังเพิ่มไฟล์ภาษาที่ไม่ต้องการลงในบันเดิลของฉันประมาณ 250 kB นอกจากนี้ฉันกำลังใช้รุ่นชั่วครู่ของซุ้มประตูและอึก

นอกจากนี้หากไม่สามารถแก้ไขได้โดยการกำหนดค่าเว็บแพคนี่เป็นลิงค์ไปยังฟังก์ชั่นที่โหลดโลแคล ฉันพยายามเพิ่ม&& module.exports.loadLocalesไปยังifคำสั่ง แต่ฉันเดา webpack ไม่จริงทำงานในลักษณะที่ว่าจะทำงาน มันก็requires ไม่ว่าสิ่งที่ ฉันคิดว่ามันใช้ regex ตอนนี้ดังนั้นฉันไม่รู้จริงๆว่าคุณจะแก้ไขได้อย่างไร


คุณพยายามใช้ช่วงเวลาผ่านnmpแทนbowerหรือไม่?
Andreas Köberle

ฉันใช้ bower สำหรับ libs ลูกค้าของฉันทั้งหมดและ npm สำหรับเครื่องมือสร้างทั้งหมดของฉัน ฉันต้องการให้เป็นเช่นนี้เพราะโครงการของฉันมีการวาง นอกจากนี้หากคุณดูคำตอบสุดท้ายของgithub.com/moment/moment/issues/1866ฉันแก้ไขปัญหาของตัวเองได้ แต่มันต้องมีการแก้ไขต้นฉบับเล็กน้อย ฉันยังไม่รู้วิธีแก้ไขปัญหานี้อย่างถูกต้องเพราะไม่รู้ว่าคุณจะแยกความแตกต่างระหว่าง node และ webpack ได้อย่างไร
epelc

คำตอบ:


305

รหัสrequire('./locale/' + name)สามารถใช้ทุกไฟล์ในlocaledir ดังนั้น webpack จึงรวมทุกไฟล์ไว้เป็นโมดูลในชุดข้อมูลของคุณ ไม่สามารถรู้ได้ว่าคุณใช้ภาษาใด

มีสองปลั๊กอินที่มีประโยชน์เพื่อให้ webpack ข้อมูลเพิ่มเติมเกี่ยวกับโมดูลที่ควรจะรวมอยู่ในชุดของคุณ: และContextReplacementPluginIgnorePlugin

require('./locale/' + name)เรียกว่าบริบท (จำเป็นต้องมีการแสดงออก) webpack infers ข้อมูลบางส่วนจากรหัสชิ้นนี้: ไดเรกทอรีและการแสดงออกปกติ ที่นี่: directory = ".../moment/locale" regular expression = /^.*$/. ดังนั้นโดยค่าเริ่มต้นทุกไฟล์ในlocaleไดเรกทอรีรวม

ContextReplacementPluginช่วยให้การแทนที่ข้อมูลสรุปเช่นให้การแสดงออกปกติใหม่ (ให้เลือกภาษาที่คุณต้องการรวม)

IgnorePluginอีกวิธีหนึ่งคือการละเว้นต้องด้วย

นี่คือตัวอย่าง:

var webpack = require("webpack");
module.exports = {
  // ...
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /de|fr|hu/)
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
};

3
คุณสามารถอธิบายวิธีใช้ตัวโหลดการข้ามได้หรือไม่? ฉันลองใหม่ `webpackreg.IgnorePlugin (/\.\/ locale \ /.+. js $ /, []) 'แต่นั่นไม่ได้ผล บริบทแทนที่ตำแหน่งปลั๊กอินยังรวมไฟล์ไว้ในชุดข้อมูลของฉันด้วยฉันคิดว่ามันไม่ได้ใช้งาน
epelc

9
คุณสามารถดูปัญหานี้ ( github.com/webpack/webpack/issues/198 ) ซึ่งมีการอภิปรายโดยละเอียดเกี่ยวกับช่วงเวลา + webpack
Tobias K.

2
ขอบคุณฉันคิดว่าnew webpack.IgnorePlugin(/^\.\/lang$/, /moment$/)จากความคิดเห็นของคุณใน GitHub จะทำงาน
epelc

16
ใน webpack docs อาร์กิวเมนต์ที่สองคืออาร์เรย์ของ regexes ฉันพยายาม plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]) ],ที่ใช้งานได้ดี
Alex K

6
@AlexKinnee สัญกรณ์เครื่องหมายวงเล็บในเอกสารหมายความว่าเป็นอาร์กิวเมนต์ตัวเลือกไม่ใช่อาร์เรย์
yangmillstheory

8

ในโครงการของเราฉันมีช่วงเวลาเช่นนี้: import moment from 'moment/src/moment';และนั่นดูเหมือนจะเป็นการหลอกลวง การใช้งานช่วงเวลาของเรานั้นง่ายมากดังนั้นฉันไม่แน่ใจว่าจะมีความไม่สอดคล้องกับ SDK หรือไม่ ฉันคิดว่าวิธีนี้ใช้งานได้เนื่องจาก WebPack ไม่ทราบวิธีการค้นหาไฟล์ภาษาแบบคงที่ดังนั้นคุณจะได้รับคำเตือน (ซึ่งง่ายต่อการซ่อนโดยการเพิ่มโฟลเดอร์ว่างที่moment/src/lib/locale/locale) แต่ไม่มีภาษารวมอยู่ด้วย


1
ไม่แน่ใจว่าวิธีการหนึ่งที่พวกนี้จะทำงานสำหรับคุณ ... ฉันก็พยายามที่จะต่อสู้ว่าgithub.com/angular/angular-cli/issues/6137แล้วก็จบลงโดยใช้github.com/ksloan/moment-mini momentไลบรารีโมดูลาร์ที่เหมาะสมจะมาพร้อมกับเวอร์ชัน 3 github.com/moment/moment/milestone/15ในบางจุด
kuncevic.dev


2

ตามคำตอบของ Adam McCrmick คุณสนิทเปลี่ยนนามแฝงเป็น:

resolve: {
    alias: {
        moment: 'moment/src/moment'
    },
},

1
เป็นเพียงคำเตือนว่าสิ่งนี้จะเปลี่ยนพฤติกรรมสำหรับโมดูลทั้งหมดที่คุณรวมไว้และอาจทำให้เกิดปัญหาที่น่าสนใจกับห้องสมุดบุคคลที่สาม มันควรจะทำงานโดยทั่วไป
Adam McCormick

1
คุณสามารถทำอย่างละเอียด? ฉันไม่ประสบกับกรณีการใช้นามแฝงทั้งหมด ในความเข้าใจของฉันมันจะสำคัญก็ต่อเมื่อคุณได้สัมผัสโมดูลนั้นในกรณี '
โมฆะ

3
เมื่อคุณตั้งค่าการแก้ปัญหานามแฝงพวกเขาจะใช้กับการใช้งานการนำเข้าหรือต้องการในระบบของคุณ (รวมถึงห้องสมุดที่คุณพึ่งพา) ดังนั้นหากโมดูลคุณขึ้นอยู่กับช่วงเวลาที่ต้องการคุณจะเปลี่ยนผลลัพธ์สำหรับโมดูลนั้นด้วย สิ่งนี้เกิดขึ้นหากคุณตั้งค่านามแฝงที่ขัดแย้งกับโมดูลโหนดในแผนผังการพึ่งพาของคุณ (เช่น "เหตุการณ์" ตัวอย่างเช่นหากการอ้างอิงของคุณใช้ไลบรารีนั้น) ในทางปฏิบัติฉันมีปัญหาเกี่ยวกับความขัดแย้งของชื่อเท่านั้นไม่ใช่การปรับแต่งพฤติกรรมเช่นนี้ แต่นี่เป็นวิธีที่อันตรายกว่าการเปลี่ยนคำสั่งการนำเข้าหนึ่งรายการ
Adam McCormick

2

ด้วยwebpack2รุ่นล่าสุดและช่วงเวลาที่คุณสามารถทำได้:

import {fn as moment} from 'moment'

จากนั้นในตัวwebpack.config.jsคุณ:

resolve: {
    packageMains: ['jsnext:main', 'main']
}

1
ฉันเดาว่าคุณหมายถึงmainFields: ...
Guillermo Grau

ดูที่ webpack2 ค่อนข้างแน่ใจว่าเปลี่ยนชื่อฟิลด์แล้ว
เควิน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.