How to make staging environment for Ember-CLI? - ember.js

There are development, test and production environments in Ember CLI.
I have test and production server. And I need to make build on test server like on production but with another environment configs. But test env in Ember CLI used for automatic tests.
I tried to call ember build --environment development on test server with next options in ember-cli-build.js file:
var app = new EmberApp(defaults, {
// Add options here
fingerprint: {
prepend: 'https://s-test.mycdn.com/',
enabled: true
}
});
But I got error:
The Broccoli Plugin: [AssetRewrite] failed with:
TypeError: Cannot read property '2' of null
.....
The broccoli plugin was instantiated at:
.....
What is right way to build ember application on test server?

This might be confusing, but what you want is not environments. You want deploy targets. Here's a great blog post about difference between the two: Do not confuse environment for deploy target (that URL has been trashed in a reorg/takeover of deveo.com but a snapshot exists on archive.org).
In Ember, environments are about how your code is minified, your assets are fingerprinted, enabling/disabling certain debugging features, etc. They are not about where you want to deploy your code, which API URL you want to use, or anything like that.
You might happen to have servers called test or development, but when deploying to these servers, you should always set environment to production, not test or development.
In order to support multiple servers (deploy targets), I would use env vars to do that. Something like:
DEPLOY_TARGET=development ember build --environment=production
DEPLOY_TARGET=test ember build --environment=production
DEPLOY_TARGET=staging ember build --environment=production
DEPLOY_TARGET=production ember build --environment=production
And in your ember-cli-deploy.js, you simply access the value through process.env.DEPLOY_TARGET, like this:
const deployTarget = process.env.DEPLOY_TARGET;
if (deployTarget === 'development') {
// ...
} else if (deployTarget === 'test') {
// ...
} else if (deployTarget === 'staging') {
// ...
} else if (deployTarget === 'production') {
// ...
}
I recommend using ember-cli-deploy addon to automate this process, so that you could just type ember deploy staging to create a build for staging and deploy it.

Unfortunately, support of environmements in ember-cli is poor. You have only development and production and can't add new ones. On top of that, production build does additional things like minifying, fingerprinting, etc, which are not necessarily needed on test/staging server and time consuming.
The good news is we have an access to Node API inside environment.js. In fact, environment.js is a node module. This allows us to add additional parameters to ember build and parse them. I'm successfuly using this trick in ember-cli 2.7 and used in 2.8 too. You will need to:
Install minimist: npm install minimist --save-dev
Add this code to the beginning of environment.js:
var argv = require('minimist')(process.argv.slice(2));
console.log('Sub-environment is set to ' + argv.subenv);
Use argv.subenv in environment.js to recognize different "sub-environments". I suggest to do this after "environment" blocks:
if (argv.subenv === 'mirage') {
ENV['ember-cli-mirage'] = {
enabled: true
};
ENV.API.namespace = '';
ENV.API.host = '';
}
if (argv.subenv === 'staging') {
ENV['ember-cli-mirage'] = {
enabled: false
};
ENV.API.host = 'https://your-server.com/';
ENV.API.namespace = '';
}
You can combine environment and argv.subenv in your code as you need.
Use your argument when building: ember build --environment=development --subenv=staging. Ember-cli will output a warning about non-supported arguments, but everything will work just fine.
Using this method, you can have as many servers as you need and build development/production version of app on any of them.
As for your error, I'm not sure what causing it, probably you may find something here

Edit your config/environment.js to set your environment when the param equals staging. For example:
```
function(environment) {
var ENV = {
// SET ENV properties
APP: {
// Here you can pass flags/options to your application instance
// when it is created
},
contentSecurityPolicy: {
// Configure security
}
};
if (environment === 'production') {
// Set production values
}
if (environment === 'staging') {
// Set staging values
}
if (environment === 'development') {
// Set staging values
}
if (environment === 'test') {
// Set testing values
}
return ENV;
};
```
And then when trying to build the version use the following command:
ember build --environment="staging"

Related

TypeError: Amplify.configure is not a function with SvelteKit + Amplify AWS

I was doing some hands on with the new SvelteKit FE using AWS Amplify to use Cognito service to authenticated my app and everything run fine in dev mode. But then, I tried to build it for deployment and this is where the fun begin...
First, I was not able to simply build the app. There was an error with Vite not able to correctly "interpret" the "browser" field!? :
'request' is not exported by __vite-browser-external, imported by node_modules/#aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
The issue is documented here (https://github.com/aws/aws-sdk-js/issues/3673) and here (https://github.com/aws-amplify/amplify-ui/issues/268).
I apply the solution suggested but ErikCH to add an alias in the svelte.config.cjs file:
resolve: {
alias: {
"./runtimeConfig": "./runtimeConfig.browser"
}
}
So now, I was back on track since the app build without an hitch. But then, I tried to run the app with an "npm run preview" but it stop dead on this message:
TypeError: Amplify.configure is not a function
I double check my code and I don't see anything missing or out of place. Here's the imports and call of that function :
...
import Amplify from '#aws-amplify/core';
import Auth from "#aws-amplify/auth";
import awsconfig from "../aws-exports";
Amplify.configure(awsconfig);
...
As mention before, the project run in dev mode, it all in pure Javascript, nothing really fancy. I updated to the latest package of everythings... here my actual version:
#sveltejs/kit": "^1.0.0-next.159
vite v2.5.1
"aws-amplify": "^4.2.5"
node v14.17.5
npm v7.21.1
I saw comments about removing completely Amplify libs and write wrappers to call Cognito directly but I found this not very productive and cumbersome. So, my last resort is the call Stackoverflow to the rescue! ;-)
Edit #1 I realize that this error occur in the app.js, that is the server side of the FE app. This is not right. This MUST run in the browser. How come it end up in the server side ???
I had to change Amplify to a named import for preview to work for me after build.
import { Amplify } from '#aws-amplify/core'
And in case anyone faced 'dev' issues with Amplify + SvelteKit, adding the following to the top of the <head> tag in app.html may help.
<script>
var global = global || window
var Buffer = Buffer || []
var process = process || { env: { DEBUG: undefined }, version: [] }
</script>
My versions:
Node.js: 14.18.0
#aws-amplify/auth: 4.3.11
#aws-amplify/core: 4.3.3
#sveltejs/kit: 1.0.0-next.190
typescript: 4.4.4
I'm not entirely sure this gets you on the right track, but one thing that has helped me out with package import weirdness, especially when it's between dev and build, is vite's optimizedDeps config directive. Perhaps something within the AWS package(s) is not liking the pre-bundling that vite is doing and you need to exclude it? This might help explain why things run fine while in dev.

How to use AWS Amplify with Sapper?

My goal is to use AWS Amplify in a Sapper project.
Creating a Sapper project from scratch (using webpack) then adding AWS Amplify and running it in dev is a success, but run it in production throws a GraphQL error in the console (Uncaught Error: Cannot use e "__Schema" from another module or realm).
Fixing this error thows another one (Uncaught ReferenceError: process is not defined).
A solution is to upgrade GraphQL from 0.13.0 to 14.0.0 unfortunatly GraphQL 0.13.0 is an AWS Amplify API dependency.
Does anyone know what can be done to get AWS Amplify work with Sapper in production ?
The link to the repo containing the source files is located here: https://github.com/ehemmerlin/sapper-aws-amplify
(Apologies for the long post but I want to be explicit)
Detailled steps
1/ Create a Sapper project using webpack (https://sapper.svelte.dev).
npx degit "sveltejs/sapper-template#webpack" my-app
cd my-app
yarn install
2/ Add AWS Amplify (https://serverless-stack.com/chapters/configure-aws-amplify.html) and lodash
yarn add aws-amplify
yarn add lodash
3/ Configure AWS Amplify (https://serverless-stack.com/chapters/configure-aws-amplify.html)
Create src/config/aws.js config file containing (change the values with yours but works as is for the purpose of this post):
export default {
s3: {
REGION: "YOUR_S3_UPLOADS_BUCKET_REGION",
BUCKET: "YOUR_S3_UPLOADS_BUCKET_NAME"
},
apiGateway: {
REGION: "YOUR_API_GATEWAY_REGION",
URL: "YOUR_API_GATEWAY_URL"
},
cognito: {
REGION: "YOUR_COGNITO_REGION",
USER_POOL_ID: "YOUR_COGNITO_USER_POOL_ID",
APP_CLIENT_ID: "YOUR_COGNITO_APP_CLIENT_ID",
IDENTITY_POOL_ID: "YOUR_IDENTITY_POOL_ID"
}
};
Add the following code to the existing code in src/client.js:
import config from './config/aws';
Amplify.configure({
Auth: {
mandatorySignIn: true,
region: config.cognito.REGION,
userPoolId: config.cognito.USER_POOL_ID,
identityPoolId: config.cognito.IDENTITY_POOL_ID,
userPoolWebClientId: config.cognito.APP_CLIENT_ID
},
Storage: {
region: config.s3.REGION,
bucket: config.s3.BUCKET,
identityPoolId: config.cognito.IDENTITY_POOL_ID
},
API: {
endpoints: [
{
name: "notes",
endpoint: config.apiGateway.URL,
region: config.apiGateway.REGION
},
]
}
});
4/ Test it
In dev (yarn run dev): it works
In production (yarn run build; node __sapper__/build): it throws an error.
Uncaught Error: Cannot use e "__Schema" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
https://yarnpkg.com/en/docs/selective-version-resolutions
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
5/ Fix it
Following the given link (https://yarnpkg.com/en/docs/selective-version-resolutions) I added this code to package.json file:
"resolutions": {
"aws-amplify/**/graphql": "^0.13.0"
}
6/ Test it
rm -rf node_modules; yarn install
Throws another error in the console (even in dev mode).
Uncaught ReferenceError: process is not defined
at Module../node_modules/graphql/jsutils/instanceOf.mjs (instanceOf.mjs:3)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/type/definition.mjs (definition.mjs:1)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/type/validate.mjs (validate.mjs:1)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/graphql.mjs (graphql.mjs:1)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/index.mjs (main.js:52896)
at \_\_webpack_require\_\_ (bootstrap:63)
A fix given by this thread (https://github.com/graphql/graphql-js/issues/1536) is to upgrade GraphQL from 0.13.0 to 14.0.0 unfortunatly GraphQL 0.13.0 is an AWS Amplify API dependency.
When building my project (I'm using npm and webpack), I got this warning,
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults
for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
which seems to be related to the schema error, as these posts indicate that the quickest fix for the error is to set NODE_ENV to production in your environment (mode is set to the NODE_ENV environment variable in the webpack config):
https://github.com/aws-amplify/amplify-js/issues/1445
https://github.com/aws-amplify/amplify-js/issues/3963
How to do that:
How to set NODE_ENV to production/development in OS X
How can I set NODE_ENV=production on Windows?
Or you can mess with the webpack config directly:
https://gist.github.com/jmannau/8039787e29190f751aa971b4a91a8901
Unfortunately some posts in those GitHub issues point out the environment variable change might not work out for a packaged app, specifically on mobile.
These posts suggest that disabling the mangler might be the next best solution:
https://github.com/graphql/graphql-js/issues/1182
https://github.com/rmosolgo/graphiql-rails/issues/58
For anyone just trying to get the basic Sapper and Amplify setup going, to reproduce this error or otherwise, I build up mine with:
npm install -g #aws-amplify/cli
npx degit "sveltejs/sapper-template#webpack" my-app
npm install
npm install aws-amplify
npm install lodash (Amplify with webpack seems to need this)
amplify configure
npm run build
amplify init (dev environment, VS Code, javascript, no framework, src directory, __sapper__\build distribution directory, default AWS profile. This generates aws-exports.js.
In src/client.js:
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);
npm run build

ember-cli disable file versioning in production build

When I run ember build --production it adds versioning to each file type. This is a problem for me as I have a compilation script that compiles the ember up then takes the file out for further processing.
How can I disable versioning of file names in production?
Edit you brocfile like below.
var app = new EmberApp({
fingerprint: {
enabled: false
}
});

How to debug ember integration test with Webstorm

I'm trying to debug a qunit ember integration test on Webstorm. Qunit is the same framework that ember is tested with.
Our test is similar to this:
import startApp from '../helpers/start-app';
var App;
module('Integration Tests', {
setup: function() {
App = startApp();
},
teardown: function() {
Ember.run(App, 'destroy');
});
test("Checking hub page",function(){
expect(2);
visit('/hub');
andThen(function(){
console.log(currentRouteName());
ok('in to the function');
});
});
I am trying these settings:
Edit------------------------------
I updated my run config but the application exits with the following error:
debugger listening on port 59771
version: 0.1.7
Could not find watchman, falling back to NodeWatcher for file system events
BuildingBuilding.Building..Building...Building...
Build successful - 1853ms.
c[?25l[8;NaNrtty.setRawMode: Use `process.stdin.setRawMode()` instead.
tty.js:37
throw new Error('can\'t set raw mode on non-tty');
^
You should have used ember to run your code. And you are running it as a simple node.js application (node foo-test.js). Moreover, Node won't accept EcmaScript 6 syntax unless being run with --harmony switch. Please make sure to update your run configuration accordingly (to run ember and pass your spec as a parameter to it)

Ember CLI fails in production

I am deploying an Ember CLI app through jenkins and publishing it using nginx. Here is by jenkins build script:
npm install
bower install
node_modules/ember-cli/bin/ember build --environment=production
The nginx configuration simply directs sub.domain.com to jenkins\jobs\lastStable\archive\dist. That works fine, but when I go the page, it is blank and the following output in the console:
TypeError: Ember.Handlebars.compile is not a function vendor-92ab6507ac60a5bf7c6819aa8fc418d6.js:18
ReferenceError: Swag is not defined spa-client-9b01c6124f5b2a4cd2e95b62be7f5ba5.js:1
I am guessing that the two errors are related, but I can't figure out what is causing them. I have tried this answer to what appears to be a similar question, but it doesn't work for me. Everything works fine in my dev environment, and I can't see anything suspicious in the Brocfile.js.
I have same issue with one of third-party libraries I'm using.
I'm using this solution: https://github.com/rwjblue/_____ember-cli-test/commit/1a26911def6f04a4badee94c8a62d8205258867b
My Brocfile.js diff:
-var app = new EmberApp();
+var app = new EmberApp({
+ vendorFiles: {
+ 'handlebars.js': {
+ production: 'bower_components/handlebars/handlebars.js'
+ }
+ }
+});
Production uses handlebars-runtime which does not include Ember.Handlebars.compile. The reason is that it's smaller to use that in production and it's more effective to precompile which ember-cli does for you automatically.
Lots of discussion on the PR found here
I encountered this same problem with the bootstrap for ember package. The temporary solution (from GH) was to inlcude the entire handlebars.js file in production:
var fileMover = require('broccoli-file-mover');
var vendorTree = fileMover('vendor', {
files: {
'handlebars/handlebars.js': 'handlebars/handlbars.runtime.js'
}
});
var app = new EmberApp({
vendorFiles: {
'handlebars.js': {
production: 'vendor/handlebars/handlebars.min.js'
}
}
});