【问题标题】:Use fullcalendar with webpack在 webpack 中使用 fullcalendar
【发布时间】:2017-01-12 06:45:43
【问题描述】:

我使用 npm、webpack 和 FullCalendar,但是在使用 fullcalendar 时在浏览器控制台中出现以下错误:

main.js:37556 Uncaught TypeError: (0 , _jquery2.default)(...).fullCalendar is not a function

我该如何解决这个问题?

我使用 FullCalendar 3.0.0-beta 和 jquery 3.1.0。我的代码如下。

index.js:

import $ from 'jquery'
import jQueryUI from 'jquery-ui'
import moment from 'moment'
import fullCalendar from 'fullcalendar'


$('#timetable').fullCalendar({
    editable: true,
    firstDay: 1,
    droppable: true,
})

webpack.config.js:

var path = require("path")
var webpack = require("webpack")
var BundleTracker = require("webpack-bundle-tracker")

module.exports = {
    context: __dirname,
    entry: [
        'fullcalendar',
        './static/index',
    ],
    output: {
        path: path.resolve('./static/bundles/'),
        filename: "[name].js",
    },

    plugins: [
        new BundleTracker({filename: './webpack-stats.json'}),
    ],

    resolve: {
        modulesDirectories: ['node_modules'],
        extensions: ['', '.js'],
    },

    module: {
        loaders:[
            { test: /\.js$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015'] } }
        ]
    }

}

【问题讨论】:

  • 你有凉亭吗?
  • @Anokrize 不,我使用 npm。

标签: javascript npm webpack fullcalendar


【解决方案1】:

我知道我在这里聚会有点晚了,但我想我还是会回答,以防有人在 Google 上发现这个问题。

每当我遇到带有 Webpack(FullCalendar 就是这样)的 jQuery 插件时,我需要确保 jQuery 本身暴露在全局命名空间中,然后插件才能通过 require/import 工作。

我的 webpack.config.js:

var webpack = require("webpack")
var path = require("path")
var ExtractTextPlugin = require("extract-text-webpack-plugin")
var HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
    entry: {
        app: "./index.js",
        vendor: [
            "jquery",
            "moment",
            "fullcalendar"
        ]
    },
    output: {
        path: path.join(__dirname, '../../public'),
        publicPath: '/',
        filename: "scripts/app.[chunkhash].js"
    },
    module: {
        loaders: [
            { test: /\.css$/, loader: ExtractTextPlugin.extract("style", ["css"]) },
            { test: require.resolve('jquery'), loader: 'expose?$!expose?jQuery' },
            { test: require.resolve('moment'), loader: 'expose?moment' }
        ]
    },
    resolve: {
      alias: {
        jquery: path.resolve(path.join(__dirname, '../..', 'node_modules', 'jquery')),
        fullcalendar: 'fullcalendar/dist/fullcalendar'
      }
    },
    plugins: [
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.CommonsChunkPlugin({ names: ["vendor"], filename: "scripts/[name].[chunkhash].js" }),
        new ExtractTextPlugin("styles/[name].[chunkhash].css"),
        new HtmlWebpackPlugin({
            template: "index.html.handlebars"
        }),
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) 
    ]
};

相关部分是 jquery 和 moment 通过 loader: 'expose?$!expose?jQuery' 语法强制位于全局命名空间中的位置。

其次,因为 fullcalendar 以一种 require 无法自动获取的方式打包,所以我设置了一个别名,以便我可以有一个干净的包名称。这是alias: { fullcalendar: 'fullcalendar/dist/fullcalendar' } 位。

这两个让我通过 require/import 加载 fullcalendar 并像往常一样使用它。

样式也需要加载。对于这个我还没有创建别名,所以我只是做了一个css文件的相对路径:

@import "../../../node_modules/fullcalendar/dist/fullcalendar.css";

您可以将 fullcalendar.js 替换为 fullcalendar.min.js 以避免重新压缩,但对于我的用例,因为我将所有供应商 JS 文件捆绑在一起,我认为如果连接更多文件,我会获得更好的压缩。 (CSS fullcalendar.cssfullcalendar.min.css 同上)

免责声明:我不知道这是否是这样做的“正确”方式,但我知道我在 webpack 上进行了相当多的试验和错误,才能让 FullCalendar 和 Select2 等 jQuery 插件正常工作,并且这个 shell 和方法确实很容易。

作为参考,我使用此模式的公共存储库中相关文件的链接:

webpack.config.js:https://github.com/thegrandpoobah/mftk-back-office/blob/e531de0a94130d6e9634ba5ab547a3e4d41c5c5f/app/src/public/webpack.config.js

样式 scss:https://github.com/thegrandpoobah/mftk-back-office/blob/e531de0a94130d6e9634ba5ab547a3e4d41c5c5f/app/src/public/styles/main.scss

我使用全日历的模块:https://github.com/thegrandpoobah/mftk-back-office/blob/e531de0a94130d6e9634ba5ab547a3e4d41c5c5f/app/src/public/students/index.js#L277

【讨论】:

  • 您的整体捆绑包大小最终是多少?当我将 jquery/fullcalendar 添加到组合中时,使用 webpack 执行此操作时我的包大小猛增了约 450KB
  • 使用 uglify 压缩时,我的供应商捆绑包大小为 1.65 MB。它包含 jquery、lodash、aviator、handlebars、moment、alpaca、用于 bootstrap、modernizr 和 fullcalendar 的 datetimepicker。如果没有 fullcalendar,它将是 1.51 MB。您从 fullcalendar.io 网站下载的 fullcalendar zip 文件的压缩版本为 213.8 KB。我的数字在这里并不准确,但它似乎至少与官方包装一致。希望有帮助!
【解决方案2】:

这是基于上述数据和其他来源的数据的分步指南。首先确保你已经安装了 moment.js:

npm install moment

然后确保您拥有完整的日历版本 3.10.2,它是版本 3 中的最新版本,没有捆绑 jQuery 和 moment.js,虽然它不是最新版本,但它使用旧语法,不会t 破坏与遗留代码的兼容性:

npm install fullcalendar@3.10.2

然后安装脚本加载器

npm install --save-dev script-loader

如果你使用 Laravel,那么在 resources/js/bootstrap.js 中在 bootstrap 和 jquery 下添加以下行(注意使用 script-lader!):

window.moment = require('moment');
require('script-loader!fullcalendar/dist/fullcalendar');
require('script-loader!fullcalendar/dist/locale-all');

然后在resources/sass/app.scss中添加css样式:

@import '~fullcalendar/dist/fullcalendar.min.css';

终于做到了:

npm run dev

或者,用于生产:

npm run prod

就是这样

【讨论】:

    【解决方案3】:

    我想我找到了一个更简单的解决方案。

    我们正在使用全日历和调度程序。我们正在从 Rails 链轮转换为 webpack。使用 webpack 将 fullcalendar 添加到延迟加载的块中会导致它引入两个额外的时刻和 jquery(是的,两个),当然,它们并没有像我们在块供应商文件中的原始版本上所做的那样选择我们的配置更改。

    理想情况下,我们只希望包含不处理任何模块的完整日历(它完全没有任何作用,而且完全没有必要)。幸运的是,你可以使用 webpack 的 script-loader 来做到这一点。

    require('script-loader!fullcalendar/dist/fullcalendar.js')
    

    你就完成了。与调度程序相同。它以隔离和未处理的方式加载它,这正是您想要的 jquery 插件。

    【讨论】:

    • 我在同一条船上,从 Rails 资产管道迁移到 Webpack,我尝试了这个,但出现错误“[Script Loader] ReferenceError: jQuery is not defined”。你是怎么处理的?
    • 我实际上使用expose-loader解决了我的问题,以便将jQuery公开为jQuery和$并公开时刻,这解决了我的问题。
    • 是的,公开这些是要走的路,尽管更好的是将 fullCalendar 升级到不依赖 jQuery 的那个。我们已经基本完成了迁移,因此不再需要任何黑客攻击。 Sprockets 目前仍在提供 CSS,但仅此而已。
    【解决方案4】:

    使用 webpack 5,下面的代码解决了这个问题:

     module: {
            rules: [
                {
                    test: require.resolve('jquery'),
                        loader: 'expose-loader',
                        options:  { 
                            exposes: ["$", "jQuery"]
                        }
                },
                {
                    test: require.resolve('moment'),
                        loader: 'expose-loader',
                        options:  { 
                            exposes: "moment"
                        }
                },
                {
                    test: require.resolve('fullcalendar'),
                    use: [
                        {
                          loader: 'script-loader',
                          options: 'fullcalendar/dist/fullcalendar.js'
                        }
                      ]
                },
                {
                    test: require.resolve('fullcalendar-scheduler'),
                    use: [
                        {
                          loader: 'script-loader',
                          options: 'fullcalendar/dist/fullcalendar-scheduler.js'
                        }
                      ]
                },
            ]
        },
    

    【讨论】:

      【解决方案5】:

      我用 fullCalendar 例如:

      $("#fullcalendar-activities").fullCalendar({
              header: {
               left: 'prev,next today',
               center: 'title',
               right: 'month,basicWeek,basicDay'
              },
              events: events,
              defaultView: 'month'
       });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-19
        • 2019-10-08
        • 2013-07-31
        • 2020-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多