私はWebpackを試してみて、 このチュートリアル の指示を試してみてください。
これは本当に単純なコードですが、このエラーについては非常に困惑しており、これは私が見逃した愚かなことだと感じています。
それぞれHandlebarsテンプレートに対応する2つのES6クラスを定義しました。アプリのエントリポイントは、インデックスファイル内のプレースホルダーHTMLをその内容で置き換えることになっています。
エントリポイント:
import './bloj.less'
// If we have a link, render the Button component on it
if (document.querySelectorAll('a').length) {
require.ensure([], () => {
const Button = require('./Components/Button.js');
const button = new Button('9gag.com');
button.render('a');
}, 'button');
}
// If we have a title, render the Header component on it
if (document.querySelectorAll('h1').length) {
require.ensure([], () => {
const Header = require('./Components/Header.js');
new Header().render('h1');
}, 'header');
}
インデックス:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>My title</h1>
<a>Click me</a>
<script src="build/bloj.js"></script>
</body>
</html>
ボタン:
import $ from 'jquery';
import './Button.less';
export default class Button {
constructor(link) {
this.link = link;
}
onClick(event) {
event.preventDefault();
alert(this.link);
}
render(node) {
const text = $(node).text();
var compiled = require('./Button.hbs');
// Render our button
$(node).html(
compiled({"text": text, "link": this.link})
);
// Attach our listeners
$('.button').click(this.onClick.bind(this));
}
}
ヘッダー:
import $ from 'jquery';
import './Header.less';
export default class Header {
render(node) {
const text = $(node).text();
var compiled = require('./Header.hbs');
// Render the header
$(node).html(
compiled({"text": text})
);
}
}
悲しいことに、それは機能せず、ページを表示するときにこれらのエラーの両方が表示されます:
Uncaught TypeError: Header is not a constructor
Uncaught TypeError: Button is not a constructor
何が欠けているのでしょうか?
私のwebpack構成は次のとおりです。
var path = require('path');
var webpack = require('webpack');
var CleanPlugin = require('clean-webpack-plugin');
var ExtractPlugin = require('extract-text-webpack-plugin');
var production = process.env.NODE_ENV === 'production';
var appName = 'bloj';
var entryPoint = './src/bloj.js';
var outputDir = './build/';
var publicDir = './build/';
// ************************************************************************** //
var plugins = [
//new ExtractPlugin(appName + '.css', {allChunks: true}),
new CleanPlugin(outputDir),
new webpack.optimize.CommonsChunkPlugin({
name: 'main',
children: true,
minChunks: 2
})
];
if (production) {
plugins = plugins.concat([
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 51200 // 50ko
}),
new webpack.optimize.UglifyJsPlugin({
mangle: true,
compress: {
warnings: false // Suppress uglification warnings
}
}),
new webpack.DefinePlugin({
__SERVER__: false,
__DEVELOPMENT__: false,
__DEVTOOLS__: false,
'process.env': {
BABEL_ENV: JSON.stringify(process.env.NODE_ENV)
}
})
]);
}
module.exports = {
entry: entryPoint,
output: {
path: outputDir,
filename: appName + '.js',
chunkFilename: '[name].js',
publicPath: publicDir
},
debug: !production,
devtool: production ? false : 'eval',
module: {
loaders: [
{
test: /\.js/,
loader: "babel",
include: path.resolve(__dirname, 'src'),
query: {
presets: ['es2015']
}
},
{
test: /\.less/,
//loader: ExtractPlugin.extract('style', 'css!less')
loader: "style!css!less"
},
{
test: /\.html/,
loader: 'html'
},
{
test: /\.hbs/,
loader: "handlebars-template-loader"
}
]
},
plugins: plugins,
node: {
fs: "empty" // Avoids Handlebars error messages
}
};
何が欠けているのでしょうか?
Babelは、デフォルトのエクスポートをdefault
プロパティに割り当てます。したがって、require
を使用してES6モジュールをインポートする場合、default
プロパティにアクセスする必要があります。
const Button = require('./Components/Button.js').default;
私はあなたがすでに答えを持っていることを理解しています。しかし、答えを見つけたのと同様の問題がありました。私自身の質問を開始し、それに答えるのは奇妙に思えます。だからここに置いておきます。
あなたと同じエラーがありました。しかし、私は自分の
export default {Class}
に
export default Class
クラスをオブジェクトでラップした理由はわかりませんが、どこかで見たのを覚えているので、使い始めました。
したがって、デフォルトでクラスを返す代わりに、このようなオブジェクトを返しました{Class: Class}
。これは完全に有効ですが、webpack + babelが壊れます。
編集:私は以来、これがおそらくbabel + webpackを壊す理由を知るようになりました。 export default
は、1つのエクスポートのみを対象としています。 javascript-objectには多くのプロパティを含めることができます。つまり、複数のエクスポートが可能です。 (参照: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export )。
複数のエクスポートを使用する場合:export {definition1, definition2}
。
ユースケース:さまざまなタイプのエディターをエクスポートするライブラリーを作成した状況でこれを使用しました(基礎となるコードは同じでしたが、使用するエクスポートによってエディターの外観が変わります)。
単にexport var __useDefault = true;
クラスをエクスポートした直後。
export default class Header {
...
}
export var __useDefault = true;
この特定の質問の問題ではありませんが、何らかの理由で、Babelは同じファイル内のクラスをホイストしません。
そのため、クラスのToken
をファイルの先頭で宣言し、後でnew Token()
と記述すると、実行されます。
コンストラクターの呼び出し後にクラスを宣言すると、xxxはコンストラクターではありませんエラーが発生します
これは特定の問題の原因ではありませんが、ES6のimport
およびexport
構文を使用していた既存のノードアプリからbabelをリッピングしようとすると、非常によく似た問題に遭遇しました。投稿は、将来これに苦労している人を助けることです。
Babelは、あるモジュールと別のモジュール間の循環依存関係を解決するため、ES6のimport
とexport
を無謀な放棄とともに使用できます。ただし、babelを削除してネイティブノードを使用する必要がある場合は、import
とexports
をrequire
に置き換える必要があります。これにより、バベルがバックグラウンドで処理していた潜在的な循環参照の問題を再導入できます。この状況に陥った場合は、コード内で次のような領域を探してください。
ファイルA:
const B = require('B');
class A {
constructor() {
this.b = new B();
}
}
module.exports = A;
ファイルB:
const A = require('A'); // this line causes the error
class B {
constructor() {
this.a = new A();
}
}
module.exports = B;
コードの構造に応じて、この問題を解決する方法はいくつかあります。おそらく最も簡単な方法は、B
クラスの新しいインスタンスを作成する代わりに、A
への参照をA
に渡すことです。 A
をロードするときに参照を動的に解決することもできます。他の無数の選択肢がありますが、これは始めるのに適した場所です。