Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move SC onto webpack #1477

Open
wants to merge 53 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
d0436a4
succeeding first build
Apr 2, 2022
efb1d01
make tests run, make most tests pass
Apr 2, 2022
3b4f844
Webpack always include full urls, where sc_static only uses partial u…
Apr 2, 2022
d7ecd90
make the year difference automatically correct (most of the time)
Apr 2, 2022
fd28564
columnCount is no longer custom per browser
Apr 2, 2022
db6a8e4
Fix a Chrome issue, where Math.pow(10,-4) is not 0.0001
Apr 6, 2022
4816664
try running tests through appveyor
Apr 6, 2022
0190c10
set minimal node version
Apr 6, 2022
4edf067
Create a separate testrunner config for CI
Apr 6, 2022
9fecfc1
try to see the node version to see why tests fail
Apr 6, 2022
22cdd0d
check whether setting node through nvm will work
Apr 6, 2022
7feaf17
make the names the same
Apr 6, 2022
23dc043
move compilerhookplugin class
Apr 6, 2022
18ac49b
add the callback back in the test runner as it is required
Apr 6, 2022
708f6b7
Fix request testing
Apr 7, 2022
51ffda3
Make CSS transition events fire every time
Apr 7, 2022
87e0d42
provide right deps for array mixin testing
Apr 8, 2022
40e2d4e
Incorrect use of .ok() causes cyclic error when converting to JSON
Apr 8, 2022
b2312f3
Remove comments and fix spelling error
Apr 8, 2022
58585db
don't use ok instead of equals
Apr 8, 2022
631f3d1
remove submodules as apps will move to a separate repo
mauritslamers Apr 23, 2022
12ba570
remove apps from tree as apps will move to a separate repo
mauritslamers Apr 23, 2022
d23e1c4
provide the external create_indexjs command
mauritslamers Apr 23, 2022
3856acd
When creating an index.js, don't scan node_modules
mauritslamers Apr 23, 2022
de80f43
make index creator skip node_modules
mauritslamers Apr 23, 2022
ebf7363
make sure the paths are relative
mauritslamers Apr 23, 2022
6b9571b
make sure sc_require doesn't cause issues
mauritslamers Apr 23, 2022
94f8010
Notes on installation and use
mauritslamers Apr 23, 2022
60dfdf7
replace $theme with #{$theme} as that is the correct syntax in sass
mauritslamers Apr 23, 2022
df8d80f
missed in previous commit
mauritslamers Apr 23, 2022
48f13b4
provide exports for source and aki_theme
mauritslamers Apr 23, 2022
a44a32d
provide imports for variables
mauritslamers Apr 23, 2022
71fbc13
also search relative from the loader
mauritslamers Apr 23, 2022
dd87346
add note for manual adjustment of main()
mauritslamers Apr 23, 2022
cfae836
Make sure SC.RootResponder.responder is not created more than once.
mauritslamers Apr 27, 2022
1d396a1
expanding on manual tasks for conversion
mauritslamers Apr 27, 2022
12ea1cc
fix typo
mauritslamers Apr 27, 2022
534ee56
Add a loader implementing a webpack safe way
mauritslamers Apr 27, 2022
5fdec79
cleanup
mauritslamers May 29, 2024
9e473a4
adding test for sc_super replacement
mauritslamers May 29, 2024
f4593d5
adding webpack library to make project webpack more light
mauritslamers May 29, 2024
853946e
move build to dist
mauritslamers May 29, 2024
98821bd
add update_indexjs command so it can be ran through npx or npm exec
mauritslamers May 29, 2024
6a89b34
commander is needed for update_index
mauritslamers May 30, 2024
d7fbde7
trying to get rid of create-sproutcore install question
mauritslamers May 30, 2024
ea348c9
undoing changes
mauritslamers May 30, 2024
5548243
should still work
mauritslamers May 30, 2024
83da557
perhaps the problem is caused by package-lock
mauritslamers May 30, 2024
7d0afcb
make script compatible with recent commander versions
mauritslamers May 30, 2024
0fa7990
whoops
mauritslamers May 30, 2024
d11c2df
framework building needs langcodes too
mauritslamers May 30, 2024
09758ae
Merge remote-tracking branch 'origin/master' into team/ml/webpack
mauritslamers May 31, 2024
b1d56fc
updating readme and add migration info
mauritslamers May 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ Gemfile*
.project
.settings/
.vscode/
node_modules
build/
dist/
6 changes: 0 additions & 6 deletions .gitmodules

This file was deleted.

151 changes: 151 additions & 0 deletions MIGRATING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Migrating from SproutCore 1.x to 2.x

## Changes

The biggest change is moving from custom build tools to webpack. This allows you
to work with many more libraries, and incorporate things built in other frameworks.
Other changes include:
- SproutCore will be compatible with ES5 strict mode
- Project structure layout is no longer compulsary
- `sc_require` is deprecated and replaced by webpack's `require`, making load order explicit.
- Every app or framework requires an `index.js` as entry point and should contain the load order. Tooling is provided to generate this `index.js`
- Framework dependencies are no longer configured in the `Buildfile` or `sc_config` but in the `index.js` of an app or framework.

## Migrating

### Step 1 - Create a (temporary) new project

Create a new project with the same name as your current one:

```
npm init sproutcore project [projectname]
```

This creates the initial project folder layout as well as the necessary webpack
configuration. While the project folder layout is no longer compulsary,
`npm init sproutcore` still generates the familiar layout.

### Step 2 - Webpack configuration

Copy over the webpack configuration files in the root of the project. Open the
`webpack.common.mjs` file and add your apps to the apps array, and frameworks to the
frameworks array.

If your project contains additional libraries, add webpack entries for
these libraries in order to be able to `require()` them in your apps `index.js`.

Webpack uses require() also for non-JS files, such as images and css. You might need to add extra rules t

### Step 3 - Package.json

If your project does not already have a `package.json` file, you can copy the `package.json`
file from the temporary new project and adjust it. If you already have a `package.json`,
please merge the `dependencies` and `devDependencies` fields from the temporary project `package.json`. Please also copy the `scripts`.

### Step 4 - npm install

Next run `npm install`

This installs all the requirements for your project.

### Step 5 - Rename css to scss where appropriate

All older versions of the SproutCore buildtools have had the tradition of treating all css
files as scss files. With webpack, that lack of distiction creates a lot of issues, so it is
easier to rename any `.css` files that you wish to be parsed as SCSS to `.scss`.

### Step 6 - index.js creation

As indicated above, every app and framework needs to have an `index.js` file with the load
order of the project files. The SproutCore build tools used a specific sorting algorithm to
decide load order based on the occurrence of `sc_require()` in a code file. To make the
transition easier, a script is included that will update or generate this index.js for you.

In every app and framework folder, please run

```
npx sproutcore create_indexjs .
```

If your framework has any dependencies on other frameworks, make sure you include a line
at the top of the generated index.js with

```
require('[dependent_frameworkname]');
```

### Step 7 - Code updates

There are some small code updates to be performed before your app will work.

SproutCore and as a consequence your app(s) were originally written with the assumption
that all files would be executed in the global namespace. Both Webpack and the JS ecosystem
have since adopted a module system and so this assumption is no longer valid: Webpack treats
every file as an individual module. The Webpack configuration included with SproutCore and
generated by its tools will wrap every file in a function having `window` as global object.
This brings in a subtle difference with the original situation as in that anything that is
not explicitly exposed to the global namespace is treated as local.


#### main.js
For every app, you will need to replace

```
function main () {
// content
}
```

with

```
window.main = function main () {
//content
}
```

#### sc_super()

You might need to update `sc_super()`.

`sc_super()` is a mechanism to call the original
method that you are overriding in either a `.create()` or `.extend()` operation. The
original build tools replaced this code with `arguments.callee.base.apply(this, arguments)`.
However, this replacement cannot be used in an ES5 strict or ES6 module environment, as the
`arguments.callee` property is no longer exposed. Luckily there is an ES5 Strict-mode
compatible alternative in the form of named methods.

The original code reading
```
myMethod: function () {
sc_super();
}
```
becomes
```
myMethod: function myMethod () {
myMethod.base.apply(this, arguments);
}
```

With SproutCore moving to webpack, webpack is configured to detect the function `sc_super`
is referring to and attempts to do this replacement for you. That should work
fine as long as you do not use the new ES6 shorthand method syntax. The code scanner
has a hard time distinguising a function invocation from the ES6 shorthand method definition,
and therefore inserts the wrong replacement.
In those cases, you can either return the ES6 shorthand to the older style function definition, or insert the `myMethod.base.apply(this, arguments)` code yourself.

### Step 7 - Run npm start

By running `npm start` in the root of your project, your project will be built and a
dev-server will start at the familiar `http://localhost:4020`.

The usual URLs should work, but in case you are in doubt, please check `http://localhost:4020/webpack-dev-server` for a list of available resources.

### Step 8 - Proxy configuration (optional)

In case your app uses a proxy, you might need to update the `webpack.dev.mjs` file to
indicate which proxy your app needs to talk to for requests not handled by the dev server.
SproutCore generates a proxy definition for every app by default to a single backend,
that you can change in `backendUrl`.
In case this is not sufficient, please replace the `proxy` definition in `webpack.dev.mjs`.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sproutcore/sproutcore?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/sproutcore/sproutcore.png?branch=master)](https://travis-ci.org/sproutcore/sproutcore)

SproutCore 2: For Native-Caliber Web Apps
=======

> **Sproutcore 2** no longer support the *Abbot Buildtools* which has been replaced by the new [Node.js Build Tools](https://github.com/sproutcore/build-tools).
> **Sproutcore 2.0** replaces the NodeJS buildtools with webpack. Migrating? Check [Migration docs](./MIGRATING.md)!

SproutCore is a JS-MVC framework for building blazing-fast, native-caliber web
applications. SproutCore's full-stack approach to single-page application
development gives you the tools you need to build rich, powerful applications...
which happen to run in the browser.

## Requirements

You need to have NodeJS installed.

## Getting Started

The easiest way to get started with SproutCore is to install the Ruby gem.
You can find instructions [here](http://sproutcore.com/install/). Once you've
got SproutCore installed, checkout the
[Getting Started](http://guides.sproutcore.com/getting_started.html) tutorial.
To create a new project, you can run the following to create a new project:

`npm init sproutcore project [projectname]`

This will give you a sample project, with a basic statechart, main view, a model and model data.

## Next Steps

Expand Down
1 change: 0 additions & 1 deletion apps/greenhouse
Submodule greenhouse deleted from 623cfe
1 change: 0 additions & 1 deletion apps/showcase
Submodule showcase deleted from 1eab66
11 changes: 11 additions & 0 deletions apps/tests/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require('./english.lproj/strings.js');
require('./core.js');
require('./controllers/source.js');
require('./controllers/target.js');
require('./controllers/targets.js');
require('./controllers/test.js');
require('./controllers/tests.js');
require('./statechart.js');
require('./views/offset_checkbox.js');
require('./english.lproj/main_page.js');
require('./main.js')
10 changes: 10 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
image: Ubuntu

install:
- nvm use 14
- npm install

test_script:
- npm run testrunner

build: off
6 changes: 6 additions & 0 deletions frameworks/ajax/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require('../core_foundation');

require('./mixins/websocket_delegate.js');
require('./system/response.js');
require('./system/request.js');
require('./system/websocket.js');
7 changes: 4 additions & 3 deletions frameworks/ajax/tests/system/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@

var url, request, contents, test_timeout=2500;

// When running Travis-CI tests through PhantomJS, wait extra long.
if (window._phantom) {
// When running Puppeteer tests through Headless Chrome, wait extra long.
if (window.webdriver) {
test_timeout=5000;
}


module("SC.Request", {

setup: function() {
Expand Down Expand Up @@ -369,7 +370,7 @@ test("Timeouts - Status listener callback", function() {
checkstop;

// make the timeout as short as possible so that it will always happen
timeoutRequest.timeoutAfter(10).notify(this, function(response) {
timeoutRequest.timeoutAfter(1).notify(this, function(response) {
start();
clearTimeout(checkstop);

Expand Down
5 changes: 5 additions & 0 deletions frameworks/bootstrap/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require('./core.js');
require('./system/browser.js');
require('./system/loader.js')
require('./system/bench.js');
require('./setup_body_class_names.js');
69 changes: 69 additions & 0 deletions frameworks/core_foundation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require('../runtime');

if (!window.$ || !window.jQuery) { // don't overwrite if already loaded
window.$ = window.jQuery = require('../jquery/jquery-3.5.0.slim.js');
}
require('../yuireset');

require('./core.js');
require('./system/browser.js');
require('./system/builder.js');
require('./system/core_query.js');
require('./system/event.js');
require('./system/cursor.js');
require('./system/responder.js');
require('./system/theme.js');
require('./system/locale.js');
require('./system/string.js');
require('./mixins/delegate_support.js');
require('./views/view/base.js');
require('./views/view/statechart.js');
require('./views/view.js');
require('./child_view_layouts/stack_layout.js');
require('./controllers/controller.js');
require('./mixins/selection_support.js');
require('./controllers/array.js');
require('./controllers/object.js');
require('./english.lproj/ordinal.js');
require('./ext/function.js');
require('./ext/object.js');
require('./ext/run_loop.js');
require('./ext/string.js');
require('./mixins/action_support.js');
require('./mixins/responder_context.js');
require('./panes/body_overflow.js');
require('./views/view/animation.js');
require('./views/view/layout_style.js');
require('./views/view/layout.js');
require('./views/view/acceleration.js');
require('./views/view/cursor.js');
require('./views/view/enabled.js');
require('./views/view/keyboard.js');
require('./views/view/manipulation.js');
require('./views/view/theming.js');
require('./views/view/touch.js');
require('./views/view/visibility.js');
require('./panes/pane.js');
require('./panes/main.js');
require('./protocols/child_view_layout_protocol.js');
require('./protocols/observable_protocol.js');
require('./protocols/responder_protocol.js');
require('./protocols/sparse_array_delegate_protocol.js');
require('./protocols/view_transition_protocol.js');
require('./system/ready.js');
require('./system/platform.js');
require('./system/touch.js');
require('./system/root_responder.js');
require('./system/application.js');
require('./system/bezier_curves.js');
require('./system/color.js');
require('./system/device.js');
require('./system/key_bindings.js');
require('./system/page.js');
require('./system/render_context.js');
require('./system/selection_set.js');
require('./system/sparse_array.js');
require('./system/timer.js');
require('./system/utils.js');
require('./system/utils/rect.js');
require('./views/view/design_mode.js')
7 changes: 4 additions & 3 deletions frameworks/core_foundation/system/root_responder.js
Original file line number Diff line number Diff line change
Expand Up @@ -2503,7 +2503,8 @@ SC.RootResponder = SC.Object.extend(
*/
SC.ready(SC.RootResponder, SC.RootResponder.ready = function () {
var r;

r = SC.RootResponder.responder = SC.RootResponder.create();
r.setup();
if (!SC.RootResponder.responder) {
r = SC.RootResponder.responder = SC.RootResponder.create();
r.setup();
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ test("set styles override style attr", function() {

test("set styles handle custom browser attributes", function() {
context.resetStyles();
context.setStyle({ columnCount: '3', mozColumnCount: '3', webkitColumnCount: '3', oColumnCount: '3', msColumnCount: '3' });
context.setStyle({ boxDirection: 'normal', mozBoxDirection: 'normal', webkitBoxDirection: 'normal', oBoxDirection: 'normal', msBoxDirection: 'normal' });
context.update();

// Browsers return single attribute styles differently, sometimes with a trailing ';'
Expand All @@ -202,7 +202,7 @@ test("set styles handle custom browser attributes", function() {
if (!style.match(/;$/)) style += ';' ;

// Older Gecko completely ignores css attributes that it doesn't understand.
if(SC.browser.isMozilla) equals(style, "-moz-column-count: 3;");
else if (SC.browser.isIE) equals(style, "-ms-column-count: 3;");
else if (SC.browser.engine === SC.ENGINE.webkit) equals(style, "-webkit-column-count: 3;");
if(SC.browser.isMozilla) equals(style, "-moz-box-direction: normal;");
else if (SC.browser.isIE) equals(style, "-ms-box-direction: normal;");
else if (SC.browser.engine === SC.ENGINE.webkit) equals(style, "-webkit-box-direction: normal;");
});
11 changes: 10 additions & 1 deletion frameworks/core_foundation/views/view/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,16 @@ SC.View.reopen(
layoutStyle = this.get('layoutStyle');

for (var styleName in layoutStyle) {
layer.style[styleName] = layoutStyle[styleName];
if (!layoutStyle.hasOwnProperty(styleName)) continue;
if (styleName !== 'transition') {
layer.style[styleName] = layoutStyle[styleName];
}
else {
// force a reflow after applying transition, otherwise
// the transition events possibly won't run
layer.style['transition'] = layoutStyle['transition'];
layer.offsetTop; // this forces a reflow
}
}

// Reset that an update is required.
Expand Down
7 changes: 7 additions & 0 deletions frameworks/core_tools/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require('./english.lproj/strings.js');
require('./core.js');
require('./data_source.js');
require('./models/target.js');
require('./fixtures/target.js');
require('./models/test.js');
require('./fixtures/test.js')