Closed Sigfried closed 7 years ago
It looks like that first error is the problem. Do you have knockout configured in your project? If you're using Aurelia CLI, make sure that you have it listed in the deps
sections, or somewhere where it's defined. Most times when you see an error saying that you can't find a module in the src
directory and the module it's looking for is just a name (like knockout), it's because in your code you tried to import "knockout", but since it's not defined in any config, it just assumes you're trying to load the file called "knockout" in the base directory.
I can't reproduce this error directly. I agree with @AStoker that situations where you want to copy files to other directories are often caused by missing path configuration in your app.
What I've done (this worked for me):
{
"name": "aurelia-knockout",
"path": "../node_modules/aurelia-knockout/dist/amd",
"main": "aurelia-knockout"
},
"knockout"
In my test I also added "aurelia-history-browser" because the app does not find the module...
Then I was able to start the app with "au run" and use knockout binding syntax in html. I only got one error in my browser console: "Uncaught ReferenceError: exports is not defined". This happend in my "aurelia-knockout" module but I don't know why. I compared this file with the corresponding file from "aurelia-templating-resources" and found no important differences. So I don't know why this is handled in another way.... Maybe someone else knows.
@code-chris, specifically what line was causing the error? It sounds like something else might be hosed, because exports
is essentially the object that we're exporting for AMD (it's the way ES6 gets transpiled to AMD). Also, wouldn't you want "knockout" defined before your "aurelia-knockout" dependency? I'm pretty sure that the dependencies are loaded in order, but it might not cause a problem if it's all modular anyway.
@AStoker Thanks for your note with the dependency order ;) The error happend on line 4 in the amd compiled "aurelia-knockout.js" file from my package:
Object.defineProperty(exports, "__esModule", {
I've seen that this code block is not surrounded with the define block in the bundle. So no exports variable is available there...
@code-chris, so you're saying that when it's in the bundled code, you don't have that module wrapped in a define block like this?
define(['exports', './aurelia-knockout-custom-attribute', './knockout-composition', './knockout-bindable'], function (exports, _aureliaKnockoutCustomAttribute, _knockoutComposition, _knockoutBindable) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.configure = exports.KnockoutBindable = exports.KnockoutCustomAttribute = undefined;
function configure(frameworkConfig) {
frameworkConfig.globalResources('./aurelia-knockout-custom-attribute');
frameworkConfig.container.get(_knockoutComposition.KnockoutComposition).register();
_aureliaKnockoutCustomAttribute.KnockoutCustomAttribute.register();
}
exports.KnockoutCustomAttribute = _aureliaKnockoutCustomAttribute.KnockoutCustomAttribute;
exports.KnockoutBindable = _knockoutBindable.KnockoutBindable;
exports.configure = configure;
});
Yes. It looks like this:
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.configure = exports.KnockoutBindable = exports.KnockoutCustomAttribute = undefined;
var _aureliaKnockoutCustomAttribute = require('./aurelia-knockout-custom-attribute');
var _knockoutComposition = require('./knockout-composition');
var _knockoutBindable = require('./knockout-bindable');
function configure(frameworkConfig) {
frameworkConfig.globalResources('./aurelia-knockout-custom-attribute');
frameworkConfig.container.get(_knockoutComposition.KnockoutComposition).register();
_aureliaKnockoutCustomAttribute.KnockoutCustomAttribute.register();
}
exports.KnockoutCustomAttribute = _aureliaKnockoutCustomAttribute.KnockoutCustomAttribute;
exports.KnockoutBindable = _knockoutBindable.KnockoutBindable;
exports.configure = configure;
The modules below and above of this are surrounded as expected.
Hm, this snippet is equal with the commonjs distro... But I've defined the amd version in aurelia.json
But the other modules like "aurelia-knockout/aurelia-knockout-custom-attribute" are included as amd...
I just followed @code-chris's instructions from 11:44am edt (except for 'added "aurelia-history-browser"', which I didn't know how to do), and I'm getting no errors so far. I was just going about it all wrong. But I have still to try to get some knockout stuff running, so I may be back... Thanks for the help!
ok. Closed, for now.
@Sigfried @code-chris, I am not able to reproduce any of the errors mentioned on a clean CLI installation. @Sigfried, based off your comments from the other error, I think you're probably messing a few things up by just copying files. If you're using the CLI do these steps.
npm install knockout aurelia-knockout --save
aurelia.json
file located in the aurelia_project
folder and add these configurations to the end of the dependencies
list under build > bundles > vendor bundle
: "knockout",
{
"name": "aurelia-knockout",
"path": "../node_modules/aurelia-knockout/dist/amd",
"main": "aurelia-knockout"
},
main.js
and add the line .plugin('aurelia-knockout')
to the aurelia.use
line. It should look like this:aurelia.use
.standardConfiguration()
.feature('resources')
.plugin('aurelia-knockout');
knockout
to a tag (not the <template>
tag) and use knockout like you normally would: <template>
<div knockout>
<h1>${message}</h1>
<h4 data-bind="text: subMessage"></h4>
</div>
</template>
Your view model can remain the same if you want.
export class App {
constructor() {
this.message = 'Hello World!';
this.subMessage = 'Hello Knockout!';
}
}
I hope this helps you get your setup @Sigfried. And perhaps @code-chris that would help documentation for installing with the CLI. The CLI is still in alpha and can be a bit complicated to figure out at first how to get things to work (especially if you're coming from JSPM/SystemJS), so it helps to have some brief docs explaining the initial setup (which thankfully isn't much).
P.S. When Github doesn't notify that the issue has been closed and you type up a response... Yah, that stinks. 😛
Thanks, @AStoker! I think your instructions are pretty much the same as @code-chris's earlier (but making the next step clearer with item 4.) I got it working with a super-simple knockout data-binding (just 'text', but that should be enough to prove it works).
So now where I'm flummoxed is that I have this whole, huge knockout app with modules managed by require.js. I'm not sure how much plumbing I'm going to have to retrofit or if there's some way to get the ES6 (or whatever) and the require.js parts to work nicely together. I'd like to start by just making a big <div knockout>...</div>
in app.html and stuff basically my whole index.html from the knockout app into it. In the Aurelia app's index.html I blindly shoved my aurelia data-main and my require.js data-main together. I'm sure this isn't the way to do it, but I'm not having any great ideas so far.
<body aurelia-app="main">
<script src="scripts/vendor-bundle.js" data-main="aurelia-bootstrapper"></script>
<script data-main="js/main" src="js/require.js"></script>
</body>
Any advice? Thanks so much again.
We have a similar situation @Sigfried, we have an application that was knockout based with Durandal. We are about to start moving it over to our Aurelia application, and have had some success with it. What we've done is use a tool called Amd-to-ES6 (https://github.com/jonbretman/amd-to-as6) to automagically make all our view models (in AMD Require syntax) into ES6 modules/classes. We did have to go through each view that we were using knockout in (which is many) and add the knockout
attribute to the div, but that's just legwork and isn't too bad.
BTW, the code snippet you had is no bueno. The vendor-bundle.js
contains requirejs in it, so you don't want to pull it in again. The aurelia-bootstrapper
will go and get your main.js
file by convention, so you shouldn't need that second script tag.
Look at this migration article. There are some topics you have to do: https://github.com/code-chris/aurelia-knockout/wiki
Thanks!
Another thing, in case it matters. We weren't using Durandal. But are the issues basically the same?
So, is your current architecture based on another single-page framework? Or did you just use knockout for data-binding?
Awesome job on the Wiki!
Yeah, awesome job on the wiki!
It is a single-page app written with knockout. You can see it here: https://github.com/OHDSI/Atlas
@AStoker, looks like I'm not going to be able to use amd-to-es6, at least not easily. The way our routing was written (https://github.com/OHDSI/Atlas/blob/master/js/app.js#L24) makes it choke on multiple module definitions.
@code-chris, I haven't quite figured out what needs to be done with amd modules based on the Wiki... I'm about to try following directions here https://github.com/code-chris/aurelia-knockout/wiki#requirejs-and-npm to see if I can keep the existing requirejs stuff for now...
Ok, I tried that, but I'm getting this error at aurelia-loader-default.js:54
:
Uncaught TypeError: Cannot read property '__useDefault' of undefined
ensureOriginOnExports @ aurelia-loader-default.js:54
(anonymous function) @ aurelia-loader-default.js:162
execCb @ require.js:29
check @ require.js:18
....
Maybe I still don't have all the pieces in place... I'll keep reading that Wiki section...
Actually, I seem to be getting pretty close. I'm still getting that error, but the app seems to be working like the original knockout app.
Sorry to be annoying...
The point I'm getting stuck now is: https://github.com/code-chris/aurelia-knockout/wiki#app-startup. When I put es6 syntax in main.js, I get main.js:1 Uncaught SyntaxError: Unexpected token export
.
Presumably the problem is just that I don't have transpiling in place. Following the wiki instructions (https://github.com/code-chris/aurelia-knockout/wiki#requirejs-and-npm) I installed the 'minimal required Aurelia modules' instead of doing au new
, which means that au run
won't work, so I'm using live-server as my web server, but that leaves out transpiling...
Spent last three hours trying to get my require config either ported to or cooperating with the webpack config from the Aurelia webpack skeleton. Giving up on that now.
If you use webpack with aurelia you don't need another module loader like requirejs. This is handled by the aurelia-loader-webpack implementation. Where are your problems with the configuration? I recommend not to use easy-webpack like in the skeletons, because you lost flexibility at some point...
Right. The reason I tried the webpack from the skeleton is that I was looking for the right way to get the es6 stuff working. It's going to be hard for me to get rid of requirejs (except gradually) because it's used so extensively in the base project.
As I mentioned before attempting to use the webpack skeleton, my app now seems fully functional though I'm calling it through <body aurelia-app="main">
and require(["aurelia-bootstrapper"])
, but main.js is just my original main.js from the knockout app (a require module). I'm not able follow the wiki's app startup instructions (https://github.com/code-chris/aurelia-knockout/wiki#app-startup):
export function configure(aurelia) => {
aurelia.use
.standardConfiguration()...
because I don't have a build process or included libraries (as far as I know) that will do the transpiling. Also, although the base knockout app is working ok, I'm still getting this error in the console: Cannot read property '__useDefault' of undefined
.
You can transpile es6 code with the babel-loader from webpack. See the README from this package: https://github.com/babel/babel-loader
Webpack creates bundles where your app and (hopefully) all dependencies are included. There is one "entry" bundle-js-file which you can use as start point. Add this script file with a <script>
to your index.html and remove the require(['aurelia-bootstrapper']). Webpack includes all files based on dependencies. So a file which is never referenced in your app will be ignored by default.
Note: You have to modify your main.js a little bit if you use webpack:
bootstrap((aurelia) => {
aurelia.use...
});
Thanks again. I seem to be getting closer, but still fairly confused. The way I'm doing it now, my main routine runs once when bundle.js gets loaded and again for the <body aurelia-app="main">
, I think: https://github.com/Sigfried/Atlas/blob/aurelia-poc/index.html#L31
Oh, sorry. You have to remove the aurelia-app="main" too.
I did that and now I'm getting Error: No applicationHost was specified.
You have to set the HTML-Element where you want to place the app.
aurelia.start().then((a) => {
a.setRoot("app", document.body);
});
Thank you. (I was just on the verge of figuring that out...glad to know I was headed in the right directions.)
Update: I finally gave up on webpack. Getting it to cooperate with requirejs was driving me nuts. Maybe I can come back to it after removing requirejs from the project. So, I've had much more success with https://github.com/icecreamliker/requirejs-babel-plugin.
Question about aurelia-knockout: Is there a way, deep inside a <div knockout>
element, to make an element that uses aurelia binding again?
If you use Aurelia Enhance on your page, I believe it works on anything on the page, including things nested from knockout
Yes, you can use aurelia bindings inside elements marked with knockout.
Only a side note to webpack: If you integrate webpack with aurelia then you can remove requirejs from your project. The aurelia-loader will with its implementation aurelia-loader-webpack load all your modules. To be backwards compatible maybe you have to polyfill the "require" function from the window context. See my unreleased solution: https://github.com/code-chris/aurelia-knockout/blob/master/src/require-polyfill.js
I'm probably just not understanding how to get aurelia-knockout set up. Others have seen a similar error (https://github.com/aurelia/bootstrapper-webpack/issues/2). Here's what I did:
After creating a new app with
au new
, Icp -r .../aurelia-knockout/dist/es2015
into.../src/aurelia-knockout
in my new app. Then (withau run --watch
) I getError: ENOENT: no such file or directory, open .../src/knockout.js
. So then I put a copy of knockout.min.js in .../src, and thenau run
doesn't complain anymore, but the browser console gives me thevendor-bundle.js:3394 TypeError: customConfig.configure is not a function
error.