I'm using the svg-sprite-loader
plug-in when trying to load an icon from an svg sprite file, however, the page fails with webpack error "exports is not defined". What could be happening? How can one debug webpack loaders like this and get more relevant error messages?
I followed this tutorial except adapting for react.
The error I'm getting is:
Icon.bs.js:21 Uncaught ReferenceError: exports is not defined
at eval (Icon.bs.js:21)
at Module../src/components/Icon/Icon.bs.js (Index.js:1357)
at __webpack_require__ (Index.js:20)
at eval (DebuggerTopBar.bs.js:6)
at Object../src/components/DebuggerTopBar/DebuggerTopBar.bs.js (Index.js:1345)
at __webpack_require__ (Index.js:20)
at eval (Debugger.bs.js:6)
at Object../src/components/Debugger/Debugger.bs.js (Index.js:1321)
at __webpack_require__ (Index.js:20)
at eval (Index.bs.js:15)
Here's all the code:
Component code
[%%raw "import '../../svg/icons.svg'"]; // this is the line that fails
[@react.component]
let make = (~name) =>
<svg className={{j|icon icon-$name|j}}>
<use xlinkHref={{j|#icons_$name|j}} />
</svg>;
Which outputs this react code
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE
'use strict';
var React = require("react");
import '../../svg/icons.svg'
;
function Icon(Props) {
var name = Props.name;
return React.createElement("svg", {
className: "icon icon-" + (String(name) + "")
}, React.createElement("use", {
xlinkHref: "#icons_" + (String(name) + "")
}));
}
var make = Icon;
exports.make = make;
/* Not a pure module */
And the generated JS
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _svg_icons_svg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../svg/icons.svg */ "./src/svg/icons.svg");
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE
var React = __webpack_require__(/*! react */ "./node_modules/react/index.js");
function Icon(Props) {
var name = Props.name;
return React.createElement("svg", {
className: "icon icon-" + (String(name) + "")
}, React.createElement("use", {
xlinkHref: "#icons_" + (String(name) + "")
}));
}
var make = Icon;
exports.make = make;
/* Not a pure module */
Webpack config
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.svg$/i,
loader: 'svg-sprite-loader'
},
]
}
Icon sprite file
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="locked" viewBox="0 0 32 32">
<path d="M9 18h-2v14h2c0.55 0 1-0.45 1-1v-12c0-0.55-0.45-1-1-1z"></path>
<path d="M23 18c-0.55 0-1 0.45-1 1v12c0 0.55 0.45 1 1 1h2v-14h-2z"></path>
<path class="handles"
d="M32 16c0-8.837-7.163-16-16-16s-16 7.163-16 16c0 1.919 0.338 3.759 0.958 5.464-0.609 1.038-0.958 2.246-0.958 3.536 0 3.526 2.608 6.443 6 6.929v-13.857c-0.997 0.143-1.927 0.495-2.742 1.012-0.168-0.835-0.258-1.699-0.258-2.584 0-7.18 5.82-13 13-13s13 5.82 13 13c0 0.885-0.088 1.749-0.257 2.584-0.816-0.517-1.745-0.87-2.743-1.013v13.858c3.392-0.485 6-3.402 6-6.929 0-1.29-0.349-2.498-0.958-3.536 0.62-1.705 0.958-3.545 0.958-5.465z"></path>
</symbol>
</defs>
</svg>
The problem seems to be that you're mixing the es6 and commonjs module systems. import
is es6 while require
and the exports
object is commonjs.
You'll have to either:
Move everything to es6. It is probably sufficient to just get BuckleScript to emit es6 by setting the package-spec to es6-global
in bsconfig.json.
Move everything to commonjs. Change import
to require
and get svg-sprite-loader
to emit commonjs by setting esModule
to false
in its options in webpack config.