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

perf: optimize imports that are not mutated or reassigned #8948

Merged
merged 6 commits into from
Jul 18, 2023
Merged

Conversation

benmccann
Copy link
Member

@benmccann benmccann commented Jul 10, 2023

closes #8933

This is especially useful for generating smaller code when using Vite's asset imports. This is not especially useful yet if using an Image.svelte component as that still won't be optimized, but if using the import directly or via a proposed preprocessor (sveltejs/kit#9787 (comment)) it will greatly reduce the size of the generated code

@dummdidumm
Copy link
Member

I vaguely remember that @tanhauhau tried something similar in the context of not rerunning $: at one point, but it resulted in false negatives (i.e., $: wasn't rerunning as expected anymore). I'm not sure if this is related or different since it only applies to primitive constant values.

@benmccann
Copy link
Member Author

Hmm. I couldn't really find anything like that in his PR history - though maybe I missed it. Could #5045 possibly be what you were thinking of? The only other things I saw that were semi-related were PRs for the @const tag, #7426, and #6525.

@benmccann benmccann changed the title perf: don't count primitive const values as dependencies perf: optimize imports that are not mutated or reassigned Jul 10, 2023
@@ -1,2 +1,2 @@
// This file is automatically generated
export default new Set(["HtmlTag","HtmlTagHydration","ResizeObserverSingleton","SvelteComponent","SvelteComponentDev","SvelteComponentTyped","SvelteElement","action_destroyer","add_attribute","add_classes","add_flush_callback","add_iframe_resize_listener","add_location","add_render_callback","add_styles","add_transform","afterUpdate","append","append_dev","append_empty_stylesheet","append_hydration","append_hydration_dev","append_styles","assign","attr","attr_dev","attribute_to_object","beforeUpdate","bind","binding_callbacks","blank_object","bubble","check_outros","children","claim_comment","claim_component","claim_element","claim_html_tag","claim_space","claim_svg_element","claim_text","clear_loops","comment","component_subscribe","compute_rest_props","compute_slots","construct_svelte_component","construct_svelte_component_dev","contenteditable_truthy_values","createEventDispatcher","create_animation","create_bidirectional_transition","create_component","create_custom_element","create_in_transition","create_out_transition","create_slot","create_ssr_component","current_component","custom_event","dataset_dev","debug","destroy_block","destroy_component","destroy_each","detach","detach_after_dev","detach_before_dev","detach_between_dev","detach_dev","dirty_components","dispatch_dev","each","element","element_is","empty","end_hydrating","ensure_array_like","ensure_array_like_dev","escape","escape_attribute_value","escape_object","exclude_internal_props","fix_and_destroy_block","fix_and_outro_and_destroy_block","fix_position","flush","flush_render_callbacks","getAllContexts","getContext","get_all_dirty_from_scope","get_binding_group_value","get_current_component","get_custom_elements_slots","get_root_for_style","get_slot_changes","get_spread_object","get_spread_update","get_store_value","get_svelte_dataset","globals","group_outros","handle_promise","hasContext","has_prop","head_selector","identity","init","init_binding_group","init_binding_group_dynamic","insert","insert_dev","insert_hydration","insert_hydration_dev","intros","invalid_attribute_name_character","is_client","is_crossorigin","is_empty","is_function","is_promise","is_void","listen","listen_dev","loop","loop_guard","merge_ssr_styles","missing_component","mount_component","noop","not_equal","now","null_to_empty","object_without_properties","onDestroy","onMount","once","outro_and_destroy_block","prevent_default","prop_dev","query_selector_all","raf","resize_observer_border_box","resize_observer_content_box","resize_observer_device_pixel_content_box","run","run_all","safe_not_equal","schedule_update","select_multiple_value","select_option","select_options","select_value","self","setContext","set_attributes","set_current_component","set_custom_element_data","set_custom_element_data_map","set_data","set_data_contenteditable","set_data_contenteditable_dev","set_data_dev","set_data_maybe_contenteditable","set_data_maybe_contenteditable_dev","set_dynamic_element_data","set_input_type","set_input_value","set_now","set_raf","set_store_value","set_style","set_svg_attributes","space","split_css_unit","spread","src_url_equal","start_hydrating","stop_immediate_propagation","stop_propagation","subscribe","svg_element","text","tick","time_ranges_to_array","to_number","toggle_class","transition_in","transition_out","trusted","update_await_block_branch","update_keyed_each","update_slot","update_slot_base","validate_component","validate_dynamic_element","validate_each_keys","validate_slots","validate_store","validate_void_dynamic_element","xlink_attr"]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like this is adding a new one for srcset_url_equal. I'm guessing this PR was not regenerated after #8868

@benmccann benmccann changed the title perf: optimize imports that are not mutated or reassigned perf: optimize handling of constant literals Jul 10, 2023
@benmccann benmccann changed the title perf: optimize handling of constant literals perf: optimize imports that are not mutated or reassigned Jul 10, 2023
@dummdidumm
Copy link
Member

What's an example snippet which shows how the code is smaller now?

@benmccann
Copy link
Member Author

This is probably not how I'd actually write this code, but is thrown together as a demo.

Input

<script>
    import avif from './example.avif';
    import webp from './example.webp';
    import img from './example.png?fallback'
</script>

<picture>
    <source srcset={avif} type="image/avif">
    <source srcset={webp} type="image/webp">
    <img src={img.src} width={img.w} height={img.h} alt="Living Carbon">
</picture>

PR

import {
	SvelteComponent,
	claim_element,
	detach,
	element,
	get_svelte_dataset,
	init,
	insert_hydration,
	noop,
	safe_not_equal
} from "svelte/internal";

import "svelte/internal/disclose-version";
import avif from './example.avif';
import webp from './example.webp';
import img from './example.png?fallback';

function create_fragment(ctx) {
	let picture;
	let textContent = `<source srcset="${avif}" type="image/avif"/> <source srcset="${webp}" type="image/webp"/> <img src="${img.src}" width="${img.w}" height="${img.h}" alt="Living Carbon"/>`;

	return {
		c() {
			picture = element("picture");
			picture.innerHTML = textContent;
		},
		l(nodes) {
			picture = claim_element(nodes, "PICTURE", { ["data-svelte-h"]: true });
			if (get_svelte_dataset(picture) !== "svelte-1ob4jd") picture.innerHTML = textContent;
		},
		m(target, anchor) {
			insert_hydration(target, picture, anchor);
		},
		p: noop,
		i: noop,
		o: noop,
		d(detaching) {
			if (detaching) {
				detach(picture);
			}
		}
	};
}

class Component extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, null, create_fragment, safe_not_equal, {});
	}
}

export default Component;

main

import {
	SvelteComponent,
	append_hydration,
	attr,
	children,
	claim_element,
	claim_space,
	detach,
	element,
	init,
	insert_hydration,
	noop,
	safe_not_equal,
	space,
	src_url_equal,
	srcset_url_equal
} from "svelte/internal";

import "svelte/internal/disclose-version";
import avif from './example.avif';
import webp from './example.webp';
import img from './example.png?fallback';

function create_fragment(ctx) {
	let picture;
	let source0;
	let source0_srcset_value;
	let t0;
	let source1;
	let source1_srcset_value;
	let t1;
	let img_1;
	let img_1_src_value;
	let img_1_width_value;
	let img_1_height_value;

	return {
		c() {
			picture = element("picture");
			source0 = element("source");
			t0 = space();
			source1 = element("source");
			t1 = space();
			img_1 = element("img");
			this.h();
		},
		l(nodes) {
			picture = claim_element(nodes, "PICTURE", {});
			var picture_nodes = children(picture);
			source0 = claim_element(picture_nodes, "SOURCE", { srcset: true, type: true });
			t0 = claim_space(picture_nodes);
			source1 = claim_element(picture_nodes, "SOURCE", { srcset: true, type: true });
			t1 = claim_space(picture_nodes);

			img_1 = claim_element(picture_nodes, "IMG", {
				src: true,
				width: true,
				height: true,
				alt: true
			});

			picture_nodes.forEach(detach);
			this.h();
		},
		h() {
			if (!srcset_url_equal(source0, source0_srcset_value = avif)) attr(source0, "srcset", source0_srcset_value);
			attr(source0, "type", "image/avif");
			if (!srcset_url_equal(source1, source1_srcset_value = webp)) attr(source1, "srcset", source1_srcset_value);
			attr(source1, "type", "image/webp");
			if (!src_url_equal(img_1.src, img_1_src_value = img.src)) attr(img_1, "src", img_1_src_value);
			attr(img_1, "width", img_1_width_value = img.w);
			attr(img_1, "height", img_1_height_value = img.h);
			attr(img_1, "alt", "Living Carbon");
		},
		m(target, anchor) {
			insert_hydration(target, picture, anchor);
			append_hydration(picture, source0);
			append_hydration(picture, t0);
			append_hydration(picture, source1);
			append_hydration(picture, t1);
			append_hydration(picture, img_1);
		},
		p: noop,
		i: noop,
		o: noop,
		d(detaching) {
			if (detaching) {
				detach(picture);
			}
		}
	};
}

class App extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, null, create_fragment, safe_not_equal, {});
	}
}

export default App;

Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the code snippet! Could you add a changeset? Then we're good to merge.

@changeset-bot
Copy link

changeset-bot bot commented Jul 18, 2023

🦋 Changeset detected

Latest commit: 2d18307

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dummdidumm dummdidumm merged commit 4bbb545 into master Jul 18, 2023
@dummdidumm dummdidumm deleted the const branch July 18, 2023 15:37
@github-actions github-actions bot mentioned this pull request Jul 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider imports that are not updated or mutated to be constant
3 participants