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

Issue 464 merge webpacker lite into webpacker v2 #650

Closed
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

- Move dev-server config options under defaults so it's transparently available in all environments

- Add new `HMR` option for hot-module-replacement


### Removed

Expand Down
25 changes: 10 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,12 @@ Similary you can also control and configure `webpack-dev-server` settings from `
# config/webpacker.yml
development:
dev_server:
host: 0.0.0.0
host: localhost
port: 8080
https: false
```

If you have `hmr` turned to true, then the `stylesheet_pack_tag` generates no output, as you will want to configure your styles to be inlined in your JavaScript for hot reloading. During production and testing, the `stylesheet_pack_tag` will create the appropriate HTML tags.

#### Resolved Paths

If you are adding webpacker to an existing app that has most of the assets inside
Expand Down Expand Up @@ -398,24 +399,18 @@ plugins:
Webpacker out-of-the-box provides CDN support using your Rails app `config.action_controller.asset_host` setting. If you already have [CDN](http://guides.rubyonrails.org/asset_pipeline.html#cdns) added in your rails app
you don't need to do anything extra for webpacker, it just works.

### HTTPS in development

If you're using the `webpack-dev-server` in development, you can serve views over HTTPS
by setting the `https` option for `webpack-dev-server` to `true` in `config/webpacker.yml`,
then start the dev server as usual with `./bin/webpack-dev-server`.

Please note that the `webpack-dev-server` will use a self-signed certificate,
so your web browser will display a warning upon accessing the page.


### Hot module replacement

Webpacker out-of-the-box doesn't ship with HMR just yet. You will need to
install additional plugins for Webpack if you want to add HMR support.
Webpacker out-of-the-box supports HMR with `webpack-dev-server` and
you can toggle it by setting `dev_server/hmr` inside webpacker.yml.

You can checkout these links on this subject:
Checkout these guide for more information:

- https://webpack.js.org/configuration/dev-server/#devserver-hot

To support HMR with React you would need to add `react-hot-loader`. Checkout this guide for
more detailed information:

- https://webpack.js.org/guides/hmr-react/


Expand Down
35 changes: 24 additions & 11 deletions lib/install/config/loaders/core/sass.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const path = require('path')
const { env } = require('../configuration.js')
const { env, settings } = require('../configuration.js')

const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
const isProduction = env.NODE_ENV === 'production'
const extractCSS = !settings.dev_server.hmr

module.exports = {
const extractOptions = {
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { minimize: isProduction } },
{ loader: 'postcss-loader', options: { sourceMap: true, config: { path: postcssConfigPath } } },
'resolve-url-loader',
{ loader: 'sass-loader', options: { sourceMap: true, indentedSyntax: true } }
]
}

// For production extract styles to a separate bundle
const extractCSSLoader = {
test: /\.(scss|sass|css)$/i,
use: ExtractTextPlugin.extract(extractOptions)
}

// For hot-reloading use regular loaders
const inlineCSSLoader = {
test: /\.(scss|sass|css)$/i,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { minimize: env.NODE_ENV === 'production' } },
{ loader: 'postcss-loader', options: { sourceMap: true, config: { path: postcssConfigPath } } },
'resolve-url-loader',
{ loader: 'sass-loader', options: { sourceMap: true } }
]
})
use: ['style-loader'].concat(extractOptions.use)
}

module.exports = isProduction || extractCSS ? extractCSSLoader : inlineCSSLoader
8 changes: 7 additions & 1 deletion lib/install/config/loaders/installers/react.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
const { join } = require('path')
const { settings } = require('../configuration.js')

module.exports = {
test: /\.(js|jsx)?(\.erb)?$/,
exclude: /node_modules/,
loader: 'babel-loader'
loader: 'babel-loader',
options: {
cacheDirectory: join(settings.cache_path, 'babel-loader')
}
}
37 changes: 4 additions & 33 deletions lib/install/config/loaders/installers/vue.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,12 @@
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const { env } = require('../configuration.js')
const { env, settings } = require('../configuration.js')

// Change it to false if you prefer Vue styles to be inlined by javascript in runtime
const extractStyles = false

const cssLoader = [
{ loader: 'css-loader', options: { minimize: env.NODE_ENV === 'production' } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
'resolve-url-loader'
]
const sassLoader = cssLoader.concat([
{ loader: 'sass-loader', options: { sourceMap: true, indentedSyntax: true } }
])
const scssLoader = cssLoader.concat([
{ loader: 'sass-loader', options: { sourceMap: true } }
])

function vueStyleLoader(loader) {
if (extractStyles) {
return ExtractTextPlugin.extract({
fallback: 'vue-style-loader',
use: loader
})
}
return ['vue-style-loader'].concat(loader)
}
const isProduction = env.NODE_ENV === 'production'
const extractCSS = !settings.dev_server.hmr

module.exports = {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
js: 'babel-loader',
file: 'file-loader',
css: vueStyleLoader(cssLoader),
scss: vueStyleLoader(scssLoader),
sass: vueStyleLoader(sassLoader)
}
extractCSS: isProduction || extractCSS
}
}
9 changes: 8 additions & 1 deletion lib/install/config/webpack/development.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect

const webpack = require('webpack')
const merge = require('webpack-merge')
const sharedConfig = require('./shared.js')
const { settings, output } = require('./configuration.js')
Expand All @@ -15,6 +16,7 @@ module.exports = merge(sharedConfig, {
clientLogLevel: 'none',
host: settings.dev_server.host,
port: settings.dev_server.port,
hot: settings.dev_server.hmr,
contentBase: output.path,
publicPath: output.publicPath,
compress: true,
Expand All @@ -26,5 +28,10 @@ module.exports = merge(sharedConfig, {
stats: {
errorDetails: true
}
}
},

plugins: settings.dev_server.hmr ? [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin()
] : []
})
1 change: 1 addition & 0 deletions lib/install/config/webpacker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ development:
dev_server:
host: localhost
port: 3035
hmr: false

test:
<<: *default
Expand Down
15 changes: 11 additions & 4 deletions lib/webpacker/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,22 @@ def fetch(key)
end

def data
if env.development?
refresh
else
if env.production?
@data ||= load
else
refresh
end
end

def load
YAML.load(config_path.read)[env].deep_symbolize_keys
if config_path.exist? &&
(@parsed_mtime.nil? ||
((config_mtime = File.mtime(config.public_manifest_path)) > @parsed_mtime))
@parsed_mtime = config_mtime
YAML.load(config_path.read)[env].deep_symbolize_keys
else
{}
end
end

def defaults
Expand Down
4 changes: 4 additions & 0 deletions lib/webpacker/dev_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def running?
false
end

def hot_module_replacing?
fetch(:hmr)
end

def host
fetch(:host)
end
Expand Down
7 changes: 6 additions & 1 deletion lib/webpacker/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ def javascript_pack_tag(*names, **options)
# in config/webpack/shared.js. By default, this list is auto-generated to match everything in
# app/javascript/packs/*.js. In production mode, the digested reference is automatically looked up.
#
# Note: If the development server is running and hot module replacement is active, this will return nothing.
# In that setup you need to configure your styles to be inlined in your JavaScript for hot reloading.
#
# Examples:
#
# # In development mode:
Expand All @@ -42,7 +45,9 @@ def javascript_pack_tag(*names, **options)
# <%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
# <link rel="stylesheet" media="screen" href="/packs/calendar-1016838bab065ae1e122.css" data-turbolinks-track="reload" />
def stylesheet_pack_tag(*names, **options)
stylesheet_link_tag(*sources_from_pack_manifest(names, type: :stylesheet), **options)
unless Webpacker.dev_server.running? && Webpacker.dev_server.hot_module_replacing?
stylesheet_link_tag(*sources_from_pack_manifest(names, type: :stylesheet), **options)
end
end

private
Expand Down
27 changes: 22 additions & 5 deletions lib/webpacker/manifest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,36 @@ def find(name)

def handle_missing_entry(name)
raise Webpacker::Manifest::MissingEntryError,
"Can't find #{name} in #{config.public_manifest_path}. Is webpack still compiling?"
"Can't find #{name} in #{config.public_manifest_path}. Manifest contains: #{@data}"
end

def missing_file_from_manifest_error(bundle_name)
msg = <<-MSG
Webpacker can't find #{bundle_name} in #{config.public_manifest_path}. Possible causes:
1. You are hot reloading.
2. You want to set Configuration.compile to true for your environment.
3. Webpack has not re-run to reflect updates.
4. You have misconfigured Webpacker's config/webpacker.yml file.
5. Your Webpack configuration is not creating a manifest.
Your manifest contains:
#{@data.to_json}
MSG
raise(Webpacker::FileLoader::NotFoundError.new(msg))
end

def data
if env.development?
refresh
else
if env.production?
@data ||= load
else
refresh
end
end

def load
if config.public_manifest_path.exist?
if config.public_manifest_path.exist? &&
(@parsed_mtime.nil? ||
((manifest_mtime = File.mtime(config.public_manifest_path)) > @parsed_mtime))
@parsed_mtime = manifest_mtime
JSON.parse config.public_manifest_path.read
else
{}
Expand Down