Getting Cesium to work with Webpacker and Rails - ruby-on-rails

I'm trying to follow these instructions to add cesium to my rails project with Webpack, but I can't figure out how to translate the instructions to work with the rails implementation of Webpack.
For example:
In webpack.config.js, we add the following above our configuration object:
// The path to the Cesium source code
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';
I assume in a rails project we would do our file imports in app/javascript/packs/application.js like this:
import 'cesium/Source';
import 'cesium/Build/Cesium/Workers';
but that gives the error:
Failed to compile.
./app/javascript/packs/application.js
Module not found: Error: Can't resolve 'cesium/Build/Cesium/Workers' in '/Users/user/Developer/appName/app/javascript/packs'
# ./app/javascript/packs/application.js 15:0-37
# multi (webpack)-dev-server/client?http://localhost:3035 ./app/javascript/packs/application.js
I've double checked, and the path is correct.
The Cesium instructions also indicate that I need to add some configuration options, but I can't figure out where I would put those since the rails webpacker gem doesn't have a webpack.config.js file. Do I just add config to the same file as the imports?

You would rather add a new config file which resolve your libs custom paths.
You can get inspiration from Webpacker documentation here:
https://github.com/rails/webpacker/blob/master/docs/webpack.md#configuration
You could do this :
//config/webpack/cesium.js
module.exports = {
resolve: {
alias: {
cesiumSource: 'cesium/Source',
cesiumWorkers: 'cesium/Build/Cesium/Workers'
}
}
}
Then merge the config options either in environment.js (global) or in development|test|production.js if this is specific to a particular environment
// config/webpack/environment.js
const { environment } = require('#rails/webpacker')
const cesiumConfig = require('./cesium')
environment.config.merge(cesiumConfig)
Hope this help.
Regards

Related

Rollup configuring alias for semantic-ui-less #import

I have been configuring rollup for creating custom react component library on top of fomantic-ui.
I have already setup the rollup.config.js
ALthough in the configuration, I need to resolve an import:
#import (multiple) '../../theme.config';
the import is part of fomantic-ui-less library, which needs to be resovled to:
path.join(__dirname, '/themes/theme.config')
and I do have themes/theme.config at my project root.
when I run build command it throws following error:
[!] (plugin postcss) Error: '../../theme.config' wasn't found. Tried - E:\Projects\UILibrary\node_modules\fomantic-ui-less\theme.config,..\..\theme.config
and I have used the rollup-plugin-postcss plugin and #rollup/plugin-alias, and called it inside plugins array
...
plugins: [
...
alias({
entries: [
find: '../../theme.config$',
replacement: path.join(__dirname, '/themes/theme.config')
]
})
postcss(),
...
]
I have also tried changing the order of plugins.
And the worst part is, it is working when configuring the storybook, using webpack alias.
.storybook/main.js
webpackFinal: async (config) => {
config.resolve.alias = {
"../../theme.config$": path.join(__dirname, "../themes/theme.config")
}
...
}

Q: How to ensure vendor chunk hash doesn't change with webpacker?

I have a Rails 6 project with webpacker 4.2.2 configured to split vendor chunks into individual files:
# config/webpack/environment.js
const { environment } = require('#rails/webpacker')
const webpack = require('webpack')
environment.config.merge({
plugins: [
new webpack.HashedModuleIdsPlugin(),
],
optimization: {
minimize: true,
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
// #see https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `npm.${packageName.replace('#', '')}`;
},
priority: 10,
},
}
}
}
})
module.exports = environment
When we precompile our assets, this produces fingerprinted files for each NPM dependency, which we upload for long-term caching and CDN-based distribution.
However, we're noticing that when we add a new library to the pack, this unexpectedly causes a rehash of many chunk files for dependencies that have not changed at all.
For example, this change in my app/javascript/packs/application.js:
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
import 'msr'
import copy from 'clipboard-copy'
+import axios from 'axios'
will produce the following change in my output chunks (produced from running bin/rails webpacker:compile):
--- a 2020-07-06 18:39:52.202440803 +0000
+++ b 2020-07-06 18:39:52.210440748 +0000
## -1,6 +1,8 ##
-application-1e8721172ae65f57286b.chunk.js
-npm.clipboard-copy-10b42ffbc97b4e927071.chunk.js
-npm.msr-01ea266e2c932167f10b.chunk.js
-npm.rails-a4564cfc542024efeb95.chunk.js
-npm.turbolinks-eeef46ff44962af9ac87.chunk.js
-npm.webpack-7226f5cf46a8c4e61c26.chunk.js
+application-bad0ed20808541f88894.chunk.js
+npm.axios-40b4b54ebace2b9e3907.chunk.js
+npm.clipboard-copy-79d2051f48603e0267e0.chunk.js
+npm.msr-f5a4252b7a7e0a94157f.chunk.js
+npm.process-cfe824ecbab5abe0eecc.chunk.js
+npm.rails-aa1c430d6ceee3ca6bd6.chunk.js
+npm.turbolinks-e28554dbfd4b75aa12e5.chunk.js
+npm.webpack-35f718d9a20b8bca2927.chunk.js
This is a double whammy because of unnecessary cache invalidation and additional CDN transfer costs.
My question is, is there a way to ensure the vendor chunk doesn't get rehashed because of dependency changes?
I don't know if this is a limitation with the way that webpack's SplitChunksPlugin works, but any advice is appreciated.
By the way, I've prepared a minimal Rails project that reproduces the situation I've described above: https://github.com/alextsui05/webpacker-vendor-chunks
A detailed summary is included in the README on the repository, and I invite any answerers to discuss based on that code.
Try setting the option moduleIds: 'hashed'
https://v4.webpack.js.org/configuration/optimization/#optimizationmoduleids

How do I access Rails environment variables in a webpacker bundle?

Is it possible to access my Rails environment variables from webpacker bundles? I know I can use dotenv, but the project uses Figaro and I would prefer not to change that. I would really like to pass the env vars from Rails to webpacker during compilation of the bundles.
I just ran into the same problem. If you put your .env file in config/webpack and then add this code to your config/webpack/application.js file, you should be good:
const dotenv = require('dotenv')
dotenv.config({path: __dirname + '/.env'})
environment.plugins.insert(
"Environment",
new webpack.EnvironmentPlugin(process.env)
)
I'm using webpacker 5.4.3 and I use dotenv-webpack to solve this problem.
yarn add -D dotenv-webpack
Put the ".env*" files in your Rails project root directory, then edit environment.js:
// config/webpack/environment.js
const { environment } = require('#rails/webpacker')
const Dotenv = require('dotenv-webpack');
environment.plugins.prepend('Dotenv', new Dotenv());
// your other settings...
module.exports = environment
Then you can access the environments through process.env
# .env
ABC=123
//packs/application.js
console.log(process.env.ABC)
// => 123

Adding Typescript to Vue + Rails app - Imports no longer work?

I'm trying to add TypeScript to an existing VueJS + Rails app. I cloned this demo (https://github.com/gbarillot/rails-vue-demo-app) then followed the instructions from https://github.com/rails/webpacker
$ bundle exec rails webpacker:install:vue
$ bundle exec rails webpacker:install:typescript
I then modified config/webpack/loaders/typescript.js as described here.
Everything seems to compile, but when I go into my "home" view and change the script to typescript:
<script lang="ts">
import Layout from '../shared/layout';
export default {
components: {
Layout
}
}
</script>
I get the following error:
Failed to compile.
/Users/matt/projects/rails-vue-demo-app/app/javascript/packs/components/home/index.vue.ts
[tsl] ERROR in /Users/matt/projects/rails-vue-demo-app/app/javascript/packs/components/home/index.vue.ts(13,20)
TS2307: Cannot find module '../shared/layout'.
Why can I no longer find the layout file when typescript is enabled?
I remember running into a similar problem for presentational components. Try adding an empty export in shared/layout so typescript can pick it up:
<script lang="ts">
export default {}
</script>

Having trouble setting up ngtemplate-loader and webpacker

I've tried setting up the webpack loader by adding this to the webpack/loaders directory
var path = require('path');
module.exports = {
test: /\.html$/,
loaders: [`ngtemplate?relativeTo=${path.join(__dirname, "/app")}`, "html"] //html?attrs[]=div:ng-include
}
and then requiring the appropriate template file from the .js code.
templateUrl: require('ngtemplate!html!./app/views/environment/index.html')
but I get the following error
Module not found: Error: Can't resolve 'html' in '/Users/joe/testrails5.1/app/javascript/app/scripts'
resolve 'html' in '/Users/joe/testrails5.1/app/javascript/app/scripts'
Parsed request is a module
Does this work for anyone else? I'm using angular 1.6 so do I need to use a different module?

Resources