diff --git a/.browserslistrc b/.browserslistrc deleted file mode 100644 index e94f8140cc..0000000000 --- a/.browserslistrc +++ /dev/null @@ -1 +0,0 @@ -defaults diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb68166db5..b8e493143f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,12 +89,10 @@ jobs: id: yarn-cache uses: actions/cache@preview with: - path: node_modules - key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }} + path: spec/dummy/node_modules + key: ${{ runner.os }}-yarn-dummy-${{ hashFiles('./package.json') }} restore-keys: | - ${{ runner.os }}-yarn- - - name: Install yarn - run: yarn install + ${{ runner.os }}-yarn-dummy- - name: Prepare database run: | bundle exec rake alchemy:spec:prepare @@ -119,7 +117,7 @@ jobs: uses: actions/cache@preview with: path: node_modules - key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }} + key: ${{ runner.os }}-yarn-${{ hashFiles('./package.json') }} restore-keys: | ${{ runner.os }}-yarn- - name: Install yarn diff --git a/.gitignore b/.gitignore index 31145e7fec..a49a90c1cb 100644 --- a/.gitignore +++ b/.gitignore @@ -9,9 +9,22 @@ pkg tmp log .sass-cache -spec/dummy/uploads/ +spec/dummy/.browserslistrc +spec/dummy/app/assets/stylesheets/alchemy/ +spec/dummy/app/javascript/ +spec/dummy/babel.config.js +spec/dummy/bin/webpack +spec/dummy/bin/webpack-dev-server +spec/dummy/config/alchemy/config.yml +spec/dummy/config/webpack/ +spec/dummy/config/webpacker.yml spec/dummy/db/*.sqlite3* -spec/dummy/public/assets +spec/dummy/package.json +spec/dummy/postcss.config.js +spec/dummy/public/assets/ +spec/dummy/public/packs/ +spec/dummy/public/packs-test/ +spec/dummy/uploads/ .rvmrc /coverage/ *.gem @@ -27,4 +40,3 @@ yarn-error.log yarn-debug.log* .yarn-integrity yarn.lock -/public/ diff --git a/Rakefile b/Rakefile index f3c0b67156..494e284beb 100644 --- a/Rakefile +++ b/Rakefile @@ -45,6 +45,7 @@ namespace :alchemy do bin/rake db:create && \ bin/rake db:environment:set && \ bin/rake db:migrate:reset && \ + bin/rails g alchemy:install --skip --skip-demo-files && \ cd - BASH result || fail diff --git a/app/helpers/alchemy/admin/base_helper.rb b/app/helpers/alchemy/admin/base_helper.rb index 70fc19ce28..617390178f 100644 --- a/app/helpers/alchemy/admin/base_helper.rb +++ b/app/helpers/alchemy/admin/base_helper.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "webpacker/helper" - module Alchemy module Admin # This module contains helper methods for rendering dialogs, toolbar buttons and confirmation windows. @@ -16,15 +14,6 @@ module Admin module BaseHelper include Alchemy::BaseHelper include Alchemy::Admin::NavigationHelper - include ::Webpacker::Helper - - def current_webpacker_instance - if controller_name == "pages" && action_name == "show" - super - else - Alchemy.webpacker - end - end # Returns a string showing the name of the currently logged in user. # diff --git a/babel.config.js b/babel.config.js index b59db95bbd..ec5616cd71 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,72 +1,12 @@ -module.exports = function (api) { - var validEnv = ["development", "test", "production"] - var currentEnv = api.env() - var isDevelopmentEnv = api.env("development") - var isProductionEnv = api.env("production") - var isTestEnv = api.env("test") - - if (!validEnv.includes(currentEnv)) { - throw new Error( - "Please specify a valid `NODE_ENV` or " + - '`BABEL_ENV` environment variables. Valid values are "development", ' + - '"test", and "production". Instead, received: ' + - JSON.stringify(currentEnv) + - "." - ) - } - - return { - presets: [ - isTestEnv && [ - "@babel/preset-env", - { - targets: { - node: "current" - } - } - ], - (isProductionEnv || isDevelopmentEnv) && [ - "@babel/preset-env", - { - forceAllTransforms: true, - useBuiltIns: "entry", - corejs: 3, - modules: false, - exclude: ["transform-typeof-symbol"] - } - ] - ].filter(Boolean), - plugins: [ - "babel-plugin-macros", - "@babel/plugin-syntax-dynamic-import", - isTestEnv && "babel-plugin-dynamic-import-node", - "@babel/plugin-transform-destructuring", - [ - "@babel/plugin-proposal-class-properties", - { - loose: true - } - ], - [ - "@babel/plugin-proposal-object-rest-spread", - { - useBuiltIns: true - } - ], - [ - "@babel/plugin-transform-runtime", - { - helpers: false, - regenerator: true, - corejs: false - } - ], - [ - "@babel/plugin-transform-regenerator", - { - async: false - } - ] - ].filter(Boolean) - } +module.exports = { + presets: [ + [ + "@babel/preset-env", + { + targets: { + node: "current" + } + } + ] + ] } diff --git a/bin/webpack b/bin/webpack deleted file mode 100755 index 334c800545..0000000000 --- a/bin/webpack +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= "development" - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -require "webpacker" -require "webpacker/webpack_runner" - -APP_ROOT = File.expand_path("..", __dir__) -Dir.chdir(APP_ROOT) do - Webpacker::WebpackRunner.run(ARGV) -end diff --git a/bin/webpack-dev-server b/bin/webpack-dev-server deleted file mode 100755 index 91025bb661..0000000000 --- a/bin/webpack-dev-server +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= "development" - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -require "webpacker" -require "webpacker/dev_server_runner" - -APP_ROOT = File.expand_path("..", __dir__) -Dir.chdir(APP_ROOT) do - Webpacker::DevServerRunner.run(ARGV) -end diff --git a/config/webpack/development.js b/config/webpack/development.js deleted file mode 100644 index c5edff94ad..0000000000 --- a/config/webpack/development.js +++ /dev/null @@ -1,5 +0,0 @@ -process.env.NODE_ENV = process.env.NODE_ENV || 'development' - -const environment = require('./environment') - -module.exports = environment.toWebpackConfig() diff --git a/config/webpack/environment.js b/config/webpack/environment.js deleted file mode 100644 index d16d9af743..0000000000 --- a/config/webpack/environment.js +++ /dev/null @@ -1,3 +0,0 @@ -const { environment } = require('@rails/webpacker') - -module.exports = environment diff --git a/config/webpack/production.js b/config/webpack/production.js deleted file mode 100644 index be0f53aacf..0000000000 --- a/config/webpack/production.js +++ /dev/null @@ -1,5 +0,0 @@ -process.env.NODE_ENV = process.env.NODE_ENV || 'production' - -const environment = require('./environment') - -module.exports = environment.toWebpackConfig() diff --git a/config/webpack/test.js b/config/webpack/test.js deleted file mode 100644 index c5edff94ad..0000000000 --- a/config/webpack/test.js +++ /dev/null @@ -1,5 +0,0 @@ -process.env.NODE_ENV = process.env.NODE_ENV || 'development' - -const environment = require('./environment') - -module.exports = environment.toWebpackConfig() diff --git a/config/webpacker.yml b/config/webpacker.yml deleted file mode 100644 index f5203b1dc0..0000000000 --- a/config/webpacker.yml +++ /dev/null @@ -1,95 +0,0 @@ -# Note: You must restart bin/webpack-dev-server for changes to take effect - -default: &default - source_path: app/javascript - source_entry_path: packs - public_root_path: public - public_output_path: alchemy-packs - cache_path: tmp/cache/webpacker - check_yarn_integrity: false - webpack_compile_output: false - - # Additional paths webpack should lookup modules - # ['app/assets', 'engine/foo/app/assets'] - resolved_paths: [] - - # Reload manifest.json on all requests so we reload latest compiled packs - cache_manifest: false - - # Extract and emit a css file - extract_css: false - - static_assets_extensions: - - .jpg - - .jpeg - - .png - - .gif - - .tiff - - .ico - - .svg - - .eot - - .otf - - .ttf - - .woff - - .woff2 - - extensions: - - .mjs - - .js - - .sass - - .scss - - .css - - .module.sass - - .module.scss - - .module.css - - .png - - .svg - - .gif - - .jpeg - - .jpg - -development: - <<: *default - compile: true - - # Verifies that versions and hashed value of the package contents in the project's package.json - check_yarn_integrity: true - - # Reference: https://webpack.js.org/configuration/dev-server/ - dev_server: - https: false - host: localhost - port: 3035 - public: localhost:3035 - hmr: false - # Inline should be set to true if using HMR - inline: true - overlay: true - compress: true - disable_host_check: true - use_local_ip: false - quiet: false - headers: - 'Access-Control-Allow-Origin': '*' - watch_options: - ignored: '**/node_modules/**' - - -test: - <<: *default - compile: true - - # Compile test packs to a separate directory - public_output_path: alchemy-packs-test - -production: - <<: *default - - # Production depends on precompilation of packs prior to booting for performance. - compile: false - - # Extract and emit a css file - extract_css: true - - # Cache manifest.json for performance - cache_manifest: true diff --git a/lib/alchemy/engine.rb b/lib/alchemy/engine.rb index 6c8f6e83e5..08b2ad8e64 100644 --- a/lib/alchemy/engine.rb +++ b/lib/alchemy/engine.rb @@ -40,28 +40,6 @@ class Engine < Rails::Engine end end - if Rails.env.development? - initializer "alchemy.webpacker.proxy" do |app| - app.middleware.insert_before( - 0, - Webpacker::DevServerProxy, - ssl_verify_none: true, - webpacker: Alchemy.webpacker, - ) - end - end - - # Serve webpacks if public file server enabled - initializer "alchemy.webpacker.middleware" do |app| - if app.config.public_file_server.enabled - app.middleware.use( - Rack::Static, - urls: ["/alchemy-packs", "/alchemy-packs-test"], - root: Alchemy::ROOT_PATH.join("public"), - ) - end - end - config.after_initialize do require_relative "./userstamp" end diff --git a/lib/alchemy/webpacker.rb b/lib/alchemy/webpacker.rb deleted file mode 100644 index 1194e75112..0000000000 --- a/lib/alchemy/webpacker.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -require "webpacker" -require "webpacker/instance" - -module Alchemy - def self.webpacker - @webpacker ||= ::Webpacker::Instance.new( - root_path: ROOT_PATH, - config_path: ROOT_PATH.join("config/webpacker.yml"), - ) - end -end diff --git a/lib/alchemy_cms.rb b/lib/alchemy_cms.rb index c58403e2fe..5cd6e4712c 100644 --- a/lib/alchemy_cms.rb +++ b/lib/alchemy_cms.rb @@ -2,7 +2,6 @@ # Instantiate the global Alchemy namespace module Alchemy YAML_WHITELIST_CLASSES = %w(Symbol Date Regexp) - ROOT_PATH = Pathname.new(File.join(__dir__, "..")) end # Require globally used external libraries @@ -26,6 +25,7 @@ module Alchemy require "select2-rails" require "turbolinks" require "userstamp" +require "webpacker" # Require globally used Alchemy mixins require_relative "alchemy/ability_helper" @@ -55,7 +55,6 @@ module Alchemy require_relative "alchemy/resource" require_relative "alchemy/tinymce" require_relative "alchemy/taggable" -require_relative "alchemy/webpacker" # Require hacks require_relative "kaminari/scoped_pagination_url_helper" diff --git a/lib/generators/alchemy/install/files/alchemy_admin.js b/lib/generators/alchemy/install/files/alchemy_admin.js new file mode 100644 index 0000000000..4691676a39 --- /dev/null +++ b/lib/generators/alchemy/install/files/alchemy_admin.js @@ -0,0 +1 @@ +import "@alchemy_cms/admin" diff --git a/lib/generators/alchemy/install/install_generator.rb b/lib/generators/alchemy/install/install_generator.rb index 0a51618f44..53c5db14d8 100644 --- a/lib/generators/alchemy/install/install_generator.rb +++ b/lib/generators/alchemy/install/install_generator.rb @@ -34,7 +34,7 @@ def install_assets end def copy_demo_views - return if @options[:skip_demo_files] + return if options[:skip_demo_files] copy_file "application.html.erb", app_views_path.join("layouts", "application.html.erb") copy_file "article.scss", app_assets_path.join("stylesheets", "alchemy", "elements", "article.scss") @@ -62,11 +62,24 @@ def install_gutentag_migrations def run_webpacker_installer unless options[:skip_webpacker_installer] + # Webpacker does not create a package.json, but we need one + unless File.exist? app_root.join("package.json") + in_root { run "echo '{}' > package.json" } + end rake("webpacker:install", abort_on_failure: true) - rake("yarn:install") end end + def add_npm_package + run "yarn add @alchemy_cms/admin" + end + + def copy_alchemy_entry_point + webpack_config = YAML.load_file(app_root.join("config", "webpacker.yml"))[Rails.env] + copy_file "alchemy_admin.js", + app_root.join(webpack_config["source_path"], webpack_config["source_entry_path"], "alchemy/admin.js") + end + private def gem_config_path diff --git a/lib/tasks/alchemy/webpacker.rake b/lib/tasks/alchemy/webpacker.rake deleted file mode 100644 index 958a334877..0000000000 --- a/lib/tasks/alchemy/webpacker.rake +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true - -namespace :alchemy do - namespace :yarn do - desc "Install Alchemy JavaScript dependencies as specified via Yarn" - task :install do - Dir.chdir(File.join(__dir__, "../..")) do - puts "🧙 Install AlchemyCMS JS bundle" - system "yarn install --no-progress --production" - end - end - end - - namespace :webpacker do - desc "Compile Alchemy JavaScript packs using webpack for production with digests" - task compile: :environment do - require "fileutils" - Webpacker.with_node_env("production") do - start = Time.now - puts "🧙 Compile AlchemyCMS JS packs" - if Alchemy.webpacker.commands.compile - FileUtils.cp_r( - Alchemy::Engine.root.join("public", "alchemy-packs"), - Rails.root.join("public"), - ) - else - # Failed compilation - exit! - end - puts "🧙 Done in #{(Time.now - start).round(2)}s." - end - end - end -end - -# Compile packs after compiled all other assets during precompilation -if Rake::Task.task_defined?("assets:precompile") - Rake::Task["assets:precompile"].enhance do - Rake::Task["alchemy:webpacker:compile"].invoke - end -else - Rake::Task.define_task("assets:precompile" => "alchemy:webpacker:compile") -end - -if Rake::Task.task_defined?("yarn:install") - Rake::Task["yarn:install"].enhance do - Rake::Task["alchemy:yarn:install"].invoke - end -else - Rake::Task.define_task("yarn:install" => "alchemy:yarn:install") -end diff --git a/package.json b/package.json index 08cf746ce8..c5150b560e 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "@alchemy_cms/admin", - "version": "0.1.0", + "version": "0.2.0", "description": "AlchemyCMS", - "browser": "app/javascript/packs/alchemy/admin.js", + "browser": "package/admin.js", "files": [ - "app/javascript/**/*" + "package/**/*" ], "directories": { - "lib": "app/javascript" + "lib": "package" }, "scripts": { "test": "jest" @@ -24,16 +24,14 @@ }, "homepage": "https://github.com/AlchemyCMS/alchemy_cms#readme", "dependencies": { - "@rails/webpacker": "^5.0.1", - "core-js": "^3", "sortablejs": "^1.10.2" }, "devDependencies": { + "@babel/core": "^7.9.6", + "@babel/preset-env": "^7.9.6", "babel-jest": "^26.0.1", "jest": "^25.2.7", "prettier": "^2.0.2", - "webpack": "^4.42.1", - "webpack-dev-server": "^3.10.3", "xhr-mock": "^2.5.1" }, "jest": { @@ -41,7 +39,7 @@ "Alchemy": {} }, "roots": [ - "app/javascript" + "package" ] } } diff --git a/app/javascript/packs/alchemy/admin.js b/package/admin.js similarity index 74% rename from app/javascript/packs/alchemy/admin.js rename to package/admin.js index 97dd75b412..ac4cdad839 100644 --- a/app/javascript/packs/alchemy/admin.js +++ b/package/admin.js @@ -1,5 +1,5 @@ -import translate from "alchemy/admin/i18n" -import NodeTree from "alchemy/admin/node_tree" +import translate from "./src/i18n" +import NodeTree from "./src/node_tree" // Global Alchemy object if (typeof window.Alchemy === "undefined") { diff --git a/app/javascript/alchemy/admin/__tests__/i18n.spec.js b/package/src/__tests__/i18n.spec.js similarity index 100% rename from app/javascript/alchemy/admin/__tests__/i18n.spec.js rename to package/src/__tests__/i18n.spec.js diff --git a/app/javascript/alchemy/admin/i18n.js b/package/src/i18n.js similarity index 100% rename from app/javascript/alchemy/admin/i18n.js rename to package/src/i18n.js diff --git a/app/javascript/alchemy/admin/node_tree.js b/package/src/node_tree.js similarity index 100% rename from app/javascript/alchemy/admin/node_tree.js rename to package/src/node_tree.js diff --git a/app/javascript/alchemy/admin/translations.js b/package/src/translations.js similarity index 100% rename from app/javascript/alchemy/admin/translations.js rename to package/src/translations.js diff --git a/app/javascript/alchemy/admin/utils/__tests__/ajax.spec.js b/package/src/utils/__tests__/ajax.spec.js similarity index 100% rename from app/javascript/alchemy/admin/utils/__tests__/ajax.spec.js rename to package/src/utils/__tests__/ajax.spec.js diff --git a/app/javascript/alchemy/admin/utils/__tests__/events.spec.js b/package/src/utils/__tests__/events.spec.js similarity index 100% rename from app/javascript/alchemy/admin/utils/__tests__/events.spec.js rename to package/src/utils/__tests__/events.spec.js diff --git a/app/javascript/alchemy/admin/utils/ajax.js b/package/src/utils/ajax.js similarity index 100% rename from app/javascript/alchemy/admin/utils/ajax.js rename to package/src/utils/ajax.js diff --git a/app/javascript/alchemy/admin/utils/events.js b/package/src/utils/events.js similarity index 100% rename from app/javascript/alchemy/admin/utils/events.js rename to package/src/utils/events.js diff --git a/spec/dummy/config/webpacker.yml b/spec/dummy/config/webpacker.yml deleted file mode 100644 index 8581ac0472..0000000000 --- a/spec/dummy/config/webpacker.yml +++ /dev/null @@ -1,96 +0,0 @@ -# Note: You must restart bin/webpack-dev-server for changes to take effect - -default: &default - source_path: app/javascript - source_entry_path: packs - public_root_path: public - public_output_path: packs - cache_path: tmp/cache/webpacker - check_yarn_integrity: false - webpack_compile_output: true - - # Additional paths webpack should lookup modules - # ['app/assets', 'engine/foo/app/assets'] - resolved_paths: [] - - # Reload manifest.json on all requests so we reload latest compiled packs - cache_manifest: false - - # Extract and emit a css file - extract_css: false - - static_assets_extensions: - - .jpg - - .jpeg - - .png - - .gif - - .tiff - - .ico - - .svg - - .eot - - .otf - - .ttf - - .woff - - .woff2 - - extensions: - - .mjs - - .js - - .sass - - .scss - - .css - - .module.sass - - .module.scss - - .module.css - - .png - - .svg - - .gif - - .jpeg - - .jpg - -development: - <<: *default - compile: true - - # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules - check_yarn_integrity: true - - # Reference: https://webpack.js.org/configuration/dev-server/ - dev_server: - https: false - host: localhost - port: 3035 - public: localhost:3035 - hmr: false - # Inline should be set to true if using HMR - inline: true - overlay: true - compress: true - disable_host_check: true - use_local_ip: false - quiet: false - pretty: false - headers: - 'Access-Control-Allow-Origin': '*' - watch_options: - ignored: '**/node_modules/**' - - -test: - <<: *default - compile: true - - # Compile test packs to a separate directory - public_output_path: packs-test - -production: - <<: *default - - # Production depends on precompilation of packs prior to booting for performance. - compile: false - - # Extract and emit a css file - extract_css: true - - # Cache manifest.json for performance - cache_manifest: true